<commit_before>/*
 * $Id$
 *
 * Copyright(C) 1998-2008 Satoshi Nakamura
 *
 */

#pragma warning(disable:4786)

#include <qmaccount.h>
#include <qmmessage.h>
#include <qmmessageholder.h>
#include <qmsecurity.h>

#include <qsinit.h>
#include <qsstl.h>

#include <algorithm>

#include <boost/bind.hpp>

#include "../model/messagecontext.h"
#include "messagemodel.h"

using namespace qm;
using namespace qs;

/****************************************************************************
 *
 * MessageModel
 *
 */

qm::MessageModel::~MessageModel()
{
}

/****************************************************************************
 *
 * AbstractMessageModel
 *
 */

qm::AbstractMessageModel::AbstractMessageModel(MessageViewMode* pDefaultMessageViewMode) :
	pDefaultMessageViewMode_(pDefaultMessageViewMode),
	pAccount_(0),
	pViewModel_(0),
	pSynchronizer_(InitThread::getInitThread().getSynchronizer()),
	bSettingMessage_(false)
{
}

qm::AbstractMessageModel::~AbstractMessageModel()
{
	if (pViewModel_)
		pViewModel_->removeViewModelHandler(this);
	setCurrentAccount(0);
}

Account* qm::AbstractMessageModel::getCurrentAccount() const
{
	return pAccount_;
}

Folder* qm::AbstractMessageModel::getCurrentFolder() const
{
	return pViewModel_ ? pViewModel_->getFolder() : 0;
}

MessageContext* qm::AbstractMessageModel::getCurrentMessage() const
{
	return pContext_.get();
}

void qm::AbstractMessageModel::setMessage(std::auto_ptr<MessageContext> pContext)
{
	struct SettingMessage
	{
		SettingMessage(bool& b) :
			b_(b)
		{
			b_ = true;
		}

		~SettingMessage()
		{
			b_ = false;
		}

		bool& b_;
	} settingMessage(bSettingMessage_);

	if (pContext.get())
		setCurrentAccount(pContext->getAccount());
	pContext_ = pContext;
	fireMessageChanged(pContext_.get());
}

void qm::AbstractMessageModel::clearMessage()
{
	setMessage(std::auto_ptr<MessageContext>());
}

void qm::AbstractMessageModel::addMessageModelHandler(MessageModelHandler* pHandler)
{
	listHandler_.push_back(pHandler);
}

void qm::AbstractMessageModel::removeMessageModelHandler(MessageModelHandler* pHandler)
{
	HandlerList::iterator it = std::remove(
		listHandler_.begin(), listHandler_.end(), pHandler);
	listHandler_.erase(it, listHandler_.end());
}

ViewModel* qm::AbstractMessageModel::getViewModel() const
{
	return pViewModel_;
}

void qm::AbstractMessageModel::setViewModel(ViewModel* pViewModel)
{
	MessageViewMode* pOldMode = 0;
	MessageViewMode* pNewMode = 0;

	if (pViewModel_) {
		pOldMode = getMessageViewMode(pViewModel_);
		pViewModel_->removeViewModelHandler(this);
	}
	pViewModel_ = pViewModel;
	if (pViewModel_) {
		pNewMode = getMessageViewMode(pViewModel_);
		pViewModel_->addViewModelHandler(this);
	}

	fireMessageViewModeChanged(pNewMode, pOldMode);
}

MessageViewMode* qm::AbstractMessageModel::getMessageViewMode()
{
	return pViewModel_ ? getMessageViewMode(pViewModel_) : pDefaultMessageViewMode_;
}

void qm::AbstractMessageModel::itemRemoved(const ViewModelEvent& event)
{
	struct RunnableImpl : public Runnable
	{
		RunnableImpl(AbstractMessageModel* pModel) :
			pModel_(pModel)
		{
		}

		virtual void run()
		{
			MessageContext* pContext = pModel_->pContext_.get();
			if (!pContext)
				return;
			MessagePtr ptr(pContext->getMessagePtr());
			if (!ptr)
				return;
			MessagePtrLock mpl(ptr);
			if (!mpl)
				pModel_->updateCurrentMessage();
		}

		AbstractMessageModel* pModel_;
	};
	asyncExec(new RunnableImpl(this));
}

void qm::AbstractMessageModel::destroyed(const ViewModelEvent& event)
{
	assert(Init::getInit().isPrimaryThread());
	assert(pViewModel_);

	setViewModel(0);
	clearMessage();
}

void qm::AbstractMessageModel::accountDestroyed(const AccountEvent& event)
{
	clearMessage();
	setCurrentAccount(0);
}

void qm::AbstractMessageModel::messageHolderKeysChanged(const MessageHolderEvent& event)
{
	if (bSettingMessage_)
		return;

	if (pContext_.get()) {
		MessagePtrLock mpl(pContext_->getMessagePtr());
		if (mpl && mpl == event.getMessageHolder())
			setMessage(std::auto_ptr<MessageContext>(
				new MessagePtrMessageContext(mpl)));
	}
}

void qm::AbstractMessageModel::setCurrentAccount(Account* pAccount)
{
	if (pAccount != pAccount_) {
		if (pAccount_) {
			pAccount_->removeMessageHolderHandler(this);
			pAccount_->removeAccountHandler(this);
		}
		pAccount_ = pAccount;
		if (pAccount_) {
			pAccount_->addAccountHandler(this);
			pAccount_->addMessageHolderHandler(this);
		}
	}
}

void qm::AbstractMessageModel::asyncExec(Runnable* pRunnable)
{
	std::auto_ptr<Runnable> p(pRunnable);
	if (Init::getInit().isPrimaryThread())
		p->run();
	else
		pSynchronizer_->asyncExec(p);
}

void qm::AbstractMessageModel::fireMessageChanged(MessageContext* pContext) const
{
	MessageModelEvent event(this, pContext);
	std::for_each(listHandler_.begin(), listHandler_.end(),
		boost::bind(&MessageModelHandler::messageChanged, _1, boost::cref(event)));
}

void qm::AbstractMessageModel::fireUpdateRestoreInfo(ViewModel::RestoreInfo* pRestoreInfo) const
{
	MessageModelRestoreEvent event(this, pRestoreInfo);
	std::for_each(listHandler_.begin(), listHandler_.end(),
		boost::bind(&MessageModelHandler::updateRestoreInfo, _1, boost::cref(event)));
}

void qm::AbstractMessageModel::fireApplyRestoreInfo(ViewModel::RestoreInfo* pRestoreInfo) const
{
	MessageModelRestoreEvent event(this, pRestoreInfo);
	std::for_each(listHandler_.begin(), listHandler_.end(),
		boost::bind(&MessageModelHandler::applyRestoreInfo, _1, boost::cref(event)));
}

/****************************************************************************
 *
 * MessageMessageModel
 *
 */

qm::MessageMessageModel::MessageMessageModel(MessageViewMode* pDefaultMessageViewMode) :
	AbstractMessageModel(pDefaultMessageViewMode)
{
}

qm::MessageMessageModel::~MessageMessageModel()
{
}

void qm::MessageMessageModel::reloadProfiles()
{
}

void qm::MessageMessageModel::updateCurrentMessage()
{
	clearMessage();
}

MessageViewMode* qm::MessageMessageModel::getMessageViewMode(ViewModel* pViewModel) const
{
	return pViewModel->getMessageViewMode(ViewModel::MODETYPE_MESSAGE);
}

/****************************************************************************
 *
 * PreviewMessageModel
 *
 */

qm::PreviewMessageModel::PreviewMessageModel(ViewModelManager* pViewModelManager,
											 Profile* pProfile,
											 bool bConnectToViewModel,
											 MessageViewMode* pDefaultMessageViewMode) :
	AbstractMessageModel(pDefaultMessageViewMode),
	pViewModelManager_(pViewModelManager),
	pProfile_(pProfile),
	nDelay_(300),
	bUpdateAlways_(false),
	bTimer_(false),
	bConnectedToViewModel_(false)
{
	reloadProfiles();

	if (bConnectToViewModel)
		connectToViewModel();

	pTimer_.reset(new Timer());
}

qm::PreviewMessageModel::~PreviewMessageModel()
{
}

void qm::PreviewMessageModel::reloadProfiles()
{
	nDelay_ = pProfile_->getInt(L"PreviewWindow", L"Delay");
	bUpdateAlways_ = pProfile_->getInt(L"PreviewWindow", L"UpdateAlways") != 0;
}

void qm::PreviewMessageModel::updateToViewModel(bool bClearIfChanged)
{
	ViewModel* pViewModel = getViewModel();
	assert(pViewModel);

	Lock<ViewModel> lock(*pViewModel);

	unsigned int nFocused = pViewModel->getFocused();
	MessageHolder* pmh = 0;
	if (nFocused < pViewModel->getCount())
		pmh = pViewModel->getMessageHolder(nFocused);

	MessageContext* pContext = getCurrentMessage();
	MessagePtrLock mpl(pContext ? pContext->getMessagePtr() : MessagePtr());
	if (pmh != mpl || (!mpl && !pmh)) {
		if (bClearIfChanged || !pmh)
			clearMessage();
		else
			setMessage(std::auto_ptr<MessageContext>(
				new MessagePtrMessageContext(pmh)));
	}
}

void qm::PreviewMessageModel::connectToViewModel()
{
	assert(!bConnectedToViewModel_);

	pViewModelManager_->addViewModelManagerHandler(this);
	setViewModel(pViewModelManager_->getCurrentViewModel());
	bConnectedToViewModel_ = true;
}

void qm::PreviewMessageModel::disconnectFromViewModel()
{
	assert(bConnectedToViewModel_);

	killTimer();

	pViewModelManager_->removeViewModelManagerHandler(this);
	setViewModel(0);
	bConnectedToViewModel_ = false;
}

bool qm::PreviewMessageModel::isConnectedToViewModel() const
{
	return bConnectedToViewModel_;
}

void qm::PreviewMessageModel::save() const
{
	ViewModel* pViewModel = getViewModel();
	if (pViewModel) {
		MessageContext* pContext = getCurrentMessage();
		MessagePtrLock mpl(pContext ? pContext->getMessagePtr() : MessagePtr());
		ViewModel::RestoreInfo info(mpl);
		if (mpl)
			fireUpdateRestoreInfo(&info);
		pViewModel->setRestoreInfo(info);
	}
}

void qm::PreviewMessageModel::itemStateChanged(const ViewModelEvent& event)
{
	assert(Init::getInit().isPrimaryThread());

	if (!(event.getMask() & ViewModelItem::FLAG_FOCUSED))
		return;

	ViewModel* pViewModel = getViewModel();
	assert(pViewModel == event.getViewModel());

	if (event.getItem() == pViewModel->getFocused()) {
		killTimer();
		if (event.isDelay() && nDelay_ != 0)
			bTimer_ = pTimer_->setTimer(TIMER_ITEMSTATECHANGED, nDelay_, this);
		else
			updateToViewModel(false);
	}
}

void qm::PreviewMessageModel::updated(const ViewModelEvent& event)
{
	struct RunnableImpl : public Runnable
	{
		RunnableImpl(PreviewMessageModel* pModel) :
			pModel_(pModel)
		{
		}

		virtual void run()
		{
			pModel_->updateToViewModel(!pModel_->bUpdateAlways_);
		}

		PreviewMessageModel* pModel_;
	};
	asyncExec(new RunnableImpl(this));
}

void qm::PreviewMessageModel::viewModelSelected(const ViewModelManagerEvent& event)
{
	killTimer();

	ViewModel* pOldViewModel = getViewModel();
	assert(pOldViewModel == event.getOldViewModel());

	if (pOldViewModel) {
		MessageContext* pContext = getCurrentMessage();
		MessagePtrLock mpl(pContext ? pContext->getMessagePtr() : MessagePtr());
		ViewModel::RestoreInfo info(mpl);
		if (mpl)
			fireUpdateRestoreInfo(&info);
		pOldViewModel->setRestoreInfo(info);
	}

	ViewModel* pNewViewModel = event.getNewViewModel();
	setViewModel(pNewViewModel);
	setCurrentAccount(pViewModelManager_->getCurrentAccount());

	if (pNewViewModel) {
		Lock<ViewModel> lock(*pNewViewModel);
		ViewModel::RestoreInfo info = pNewViewModel->getRestoreInfo();
		MessagePtrLock mpl(info.getMessagePtr());
		if (mpl) {
			setMessage(std::auto_ptr<MessageContext>(
				new MessagePtrMessageContext(mpl)));
			fireApplyRestoreInfo(&info);
		}
		else {
			updateCurrentMessage();
		}
	}
	else {
		clearMessage();
	}
}

void qm::PreviewMessageModel::timerTimeout(Timer::Id nId)
{
	killTimer();
	updateToViewModel(false);
}

void qm::PreviewMessageModel::updateCurrentMessage()
{
	if (bUpdateAlways_)
		updateToViewModel(false);
	else
		clearMessage();
}

MessageViewMode* qm::PreviewMessageModel::getMessageViewMode(ViewModel* pViewModel) const
{
	return pViewModel->getMessageViewMode(ViewModel::MODETYPE_PREVIEW);
}

void qm::PreviewMessageModel::killTimer()
{
	if (!bTimer_)
		return;

	pTimer_->killTimer(TIMER_ITEMSTATECHANGED);
	bTimer_ = false;
}

/****************************************************************************
 *
 * MessageModelHandler
 *
 */

qm::MessageModelHandler::~MessageModelHandler()
{
}

/****************************************************************************
 *
 * MessageModelEvent
 *
 */

qm::MessageModelEvent::MessageModelEvent(const MessageModel* pModel,
										 MessageContext* pContext) :
	pModel_(pModel),
	pContext_(pContext)
{
}

qm::MessageModelEvent::~MessageModelEvent()
{
}

const MessageModel* qm::MessageModelEvent::getMessageModel() const
{
	return pModel_;
}

MessageContext* qm::MessageModelEvent::getMessageContext() const
{
	return pContext_;
}

/****************************************************************************
 *
 * MessageModelRestoreEvent
 *
 */

qm::MessageModelRestoreEvent::MessageModelRestoreEvent(const MessageModel* pModel,
													   ViewModel::RestoreInfo* pRestoreInfo) :
	pModel_(pModel),
	pRestoreInfo_(pRestoreInfo)
{
}

qm::MessageModelRestoreEvent::~MessageModelRestoreEvent()
{
}

const MessageModel* qm::MessageModelRestoreEvent::getMessageModel() const
{
	return pModel_;
}

ViewModel::RestoreInfo* qm::MessageModelRestoreEvent::getRestoreInfo() const
{
	return pRestoreInfo_;
}
<commit_msg>Fixed AbstractMessageModel::messageHolderKeysChanged handles an event in a background thread, which made a sync thread halt.<commit_after>/*
 * $Id$
 *
 * Copyright(C) 1998-2008 Satoshi Nakamura
 *
 */

#pragma warning(disable:4786)

#include <qmaccount.h>
#include <qmmessage.h>
#include <qmmessageholder.h>
#include <qmsecurity.h>

#include <qsinit.h>
#include <qsstl.h>

#include <algorithm>

#include <boost/bind.hpp>

#include "../model/messagecontext.h"
#include "messagemodel.h"

using namespace qm;
using namespace qs;

/****************************************************************************
 *
 * MessageModel
 *
 */

qm::MessageModel::~MessageModel()
{
}

/****************************************************************************
 *
 * AbstractMessageModel
 *
 */

qm::AbstractMessageModel::AbstractMessageModel(MessageViewMode* pDefaultMessageViewMode) :
	pDefaultMessageViewMode_(pDefaultMessageViewMode),
	pAccount_(0),
	pViewModel_(0),
	pSynchronizer_(InitThread::getInitThread().getSynchronizer()),
	bSettingMessage_(false)
{
}

qm::AbstractMessageModel::~AbstractMessageModel()
{
	if (pViewModel_)
		pViewModel_->removeViewModelHandler(this);
	setCurrentAccount(0);
}

Account* qm::AbstractMessageModel::getCurrentAccount() const
{
	return pAccount_;
}

Folder* qm::AbstractMessageModel::getCurrentFolder() const
{
	return pViewModel_ ? pViewModel_->getFolder() : 0;
}

MessageContext* qm::AbstractMessageModel::getCurrentMessage() const
{
	return pContext_.get();
}

void qm::AbstractMessageModel::setMessage(std::auto_ptr<MessageContext> pContext)
{
	assert(Init::getInit().isPrimaryThread());

	struct SettingMessage
	{
		SettingMessage(bool& b) :
			b_(b)
		{
			b_ = true;
		}

		~SettingMessage()
		{
			b_ = false;
		}

		bool& b_;
	} settingMessage(bSettingMessage_);

	if (pContext.get())
		setCurrentAccount(pContext->getAccount());
	pContext_ = pContext;

	fireMessageChanged(pContext_.get());
}

void qm::AbstractMessageModel::clearMessage()
{
	setMessage(std::auto_ptr<MessageContext>());
}

void qm::AbstractMessageModel::addMessageModelHandler(MessageModelHandler* pHandler)
{
	listHandler_.push_back(pHandler);
}

void qm::AbstractMessageModel::removeMessageModelHandler(MessageModelHandler* pHandler)
{
	HandlerList::iterator it = std::remove(
		listHandler_.begin(), listHandler_.end(), pHandler);
	listHandler_.erase(it, listHandler_.end());
}

ViewModel* qm::AbstractMessageModel::getViewModel() const
{
	return pViewModel_;
}

void qm::AbstractMessageModel::setViewModel(ViewModel* pViewModel)
{
	MessageViewMode* pOldMode = 0;
	MessageViewMode* pNewMode = 0;

	if (pViewModel_) {
		pOldMode = getMessageViewMode(pViewModel_);
		pViewModel_->removeViewModelHandler(this);
	}
	pViewModel_ = pViewModel;
	if (pViewModel_) {
		pNewMode = getMessageViewMode(pViewModel_);
		pViewModel_->addViewModelHandler(this);
	}

	fireMessageViewModeChanged(pNewMode, pOldMode);
}

MessageViewMode* qm::AbstractMessageModel::getMessageViewMode()
{
	return pViewModel_ ? getMessageViewMode(pViewModel_) : pDefaultMessageViewMode_;
}

void qm::AbstractMessageModel::itemRemoved(const ViewModelEvent& event)
{
	struct RunnableImpl : public Runnable
	{
		RunnableImpl(AbstractMessageModel* pModel) :
			pModel_(pModel)
		{
		}

		virtual void run()
		{
			MessageContext* pContext = pModel_->pContext_.get();
			if (!pContext)
				return;
			MessagePtr ptr(pContext->getMessagePtr());
			if (!ptr)
				return;
			MessagePtrLock mpl(ptr);
			if (!mpl)
				pModel_->updateCurrentMessage();
		}

		AbstractMessageModel* pModel_;
	};
	asyncExec(new RunnableImpl(this));
}

void qm::AbstractMessageModel::destroyed(const ViewModelEvent& event)
{
	assert(Init::getInit().isPrimaryThread());
	assert(pViewModel_);

	setViewModel(0);
	clearMessage();
}

void qm::AbstractMessageModel::accountDestroyed(const AccountEvent& event)
{
	clearMessage();
	setCurrentAccount(0);
}

void qm::AbstractMessageModel::messageHolderKeysChanged(const MessageHolderEvent& event)
{
	if (Init::getInit().isPrimaryThread() && bSettingMessage_)
		return;

	struct RunnableImpl : public Runnable
	{
		RunnableImpl(AbstractMessageModel* pModel,
					 const MessagePtr& ptr) :
			pModel_(pModel),
			ptr_(ptr)
		{
		}

		virtual void run()
		{
			MessageContext* pContext = pModel_->pContext_.get();
			if (!pContext)
				return;
			MessagePtr ptr(pContext->getMessagePtr());
			if (ptr != ptr_)
				return;
			MessagePtrLock mpl(ptr);
			if (mpl)
				pModel_->setMessage(std::auto_ptr<MessageContext>(
					new MessagePtrMessageContext(mpl)));
		}

		AbstractMessageModel* pModel_;
		MessagePtr ptr_;
	};
	asyncExec(new RunnableImpl(this, event.getMessageHolder()));
}

void qm::AbstractMessageModel::setCurrentAccount(Account* pAccount)
{
	if (pAccount != pAccount_) {
		if (pAccount_) {
			pAccount_->removeMessageHolderHandler(this);
			pAccount_->removeAccountHandler(this);
		}
		pAccount_ = pAccount;
		if (pAccount_) {
			pAccount_->addAccountHandler(this);
			pAccount_->addMessageHolderHandler(this);
		}
	}
}

void qm::AbstractMessageModel::asyncExec(Runnable* pRunnable)
{
	std::auto_ptr<Runnable> p(pRunnable);
	if (Init::getInit().isPrimaryThread())
		p->run();
	else
		pSynchronizer_->asyncExec(p);
}

void qm::AbstractMessageModel::fireMessageChanged(MessageContext* pContext) const
{
	MessageModelEvent event(this, pContext);
	std::for_each(listHandler_.begin(), listHandler_.end(),
		boost::bind(&MessageModelHandler::messageChanged, _1, boost::cref(event)));
}

void qm::AbstractMessageModel::fireUpdateRestoreInfo(ViewModel::RestoreInfo* pRestoreInfo) const
{
	MessageModelRestoreEvent event(this, pRestoreInfo);
	std::for_each(listHandler_.begin(), listHandler_.end(),
		boost::bind(&MessageModelHandler::updateRestoreInfo, _1, boost::cref(event)));
}

void qm::AbstractMessageModel::fireApplyRestoreInfo(ViewModel::RestoreInfo* pRestoreInfo) const
{
	MessageModelRestoreEvent event(this, pRestoreInfo);
	std::for_each(listHandler_.begin(), listHandler_.end(),
		boost::bind(&MessageModelHandler::applyRestoreInfo, _1, boost::cref(event)));
}

/****************************************************************************
 *
 * MessageMessageModel
 *
 */

qm::MessageMessageModel::MessageMessageModel(MessageViewMode* pDefaultMessageViewMode) :
	AbstractMessageModel(pDefaultMessageViewMode)
{
}

qm::MessageMessageModel::~MessageMessageModel()
{
}

void qm::MessageMessageModel::reloadProfiles()
{
}

void qm::MessageMessageModel::updateCurrentMessage()
{
	clearMessage();
}

MessageViewMode* qm::MessageMessageModel::getMessageViewMode(ViewModel* pViewModel) const
{
	return pViewModel->getMessageViewMode(ViewModel::MODETYPE_MESSAGE);
}

/****************************************************************************
 *
 * PreviewMessageModel
 *
 */

qm::PreviewMessageModel::PreviewMessageModel(ViewModelManager* pViewModelManager,
											 Profile* pProfile,
											 bool bConnectToViewModel,
											 MessageViewMode* pDefaultMessageViewMode) :
	AbstractMessageModel(pDefaultMessageViewMode),
	pViewModelManager_(pViewModelManager),
	pProfile_(pProfile),
	nDelay_(300),
	bUpdateAlways_(false),
	bTimer_(false),
	bConnectedToViewModel_(false)
{
	reloadProfiles();

	if (bConnectToViewModel)
		connectToViewModel();

	pTimer_.reset(new Timer());
}

qm::PreviewMessageModel::~PreviewMessageModel()
{
}

void qm::PreviewMessageModel::reloadProfiles()
{
	nDelay_ = pProfile_->getInt(L"PreviewWindow", L"Delay");
	bUpdateAlways_ = pProfile_->getInt(L"PreviewWindow", L"UpdateAlways") != 0;
}

void qm::PreviewMessageModel::updateToViewModel(bool bClearIfChanged)
{
	ViewModel* pViewModel = getViewModel();
	assert(pViewModel);

	Lock<ViewModel> lock(*pViewModel);

	unsigned int nFocused = pViewModel->getFocused();
	MessageHolder* pmh = 0;
	if (nFocused < pViewModel->getCount())
		pmh = pViewModel->getMessageHolder(nFocused);

	MessageContext* pContext = getCurrentMessage();
	MessagePtrLock mpl(pContext ? pContext->getMessagePtr() : MessagePtr());
	if (pmh != mpl || (!mpl && !pmh)) {
		if (bClearIfChanged || !pmh)
			clearMessage();
		else
			setMessage(std::auto_ptr<MessageContext>(
				new MessagePtrMessageContext(pmh)));
	}
}

void qm::PreviewMessageModel::connectToViewModel()
{
	assert(!bConnectedToViewModel_);

	pViewModelManager_->addViewModelManagerHandler(this);
	setViewModel(pViewModelManager_->getCurrentViewModel());
	bConnectedToViewModel_ = true;
}

void qm::PreviewMessageModel::disconnectFromViewModel()
{
	assert(bConnectedToViewModel_);

	killTimer();

	pViewModelManager_->removeViewModelManagerHandler(this);
	setViewModel(0);
	bConnectedToViewModel_ = false;
}

bool qm::PreviewMessageModel::isConnectedToViewModel() const
{
	return bConnectedToViewModel_;
}

void qm::PreviewMessageModel::save() const
{
	ViewModel* pViewModel = getViewModel();
	if (pViewModel) {
		MessageContext* pContext = getCurrentMessage();
		MessagePtrLock mpl(pContext ? pContext->getMessagePtr() : MessagePtr());
		ViewModel::RestoreInfo info(mpl);
		if (mpl)
			fireUpdateRestoreInfo(&info);
		pViewModel->setRestoreInfo(info);
	}
}

void qm::PreviewMessageModel::itemStateChanged(const ViewModelEvent& event)
{
	assert(Init::getInit().isPrimaryThread());

	if (!(event.getMask() & ViewModelItem::FLAG_FOCUSED))
		return;

	ViewModel* pViewModel = getViewModel();
	assert(pViewModel == event.getViewModel());

	if (event.getItem() == pViewModel->getFocused()) {
		killTimer();
		if (event.isDelay() && nDelay_ != 0)
			bTimer_ = pTimer_->setTimer(TIMER_ITEMSTATECHANGED, nDelay_, this);
		else
			updateToViewModel(false);
	}
}

void qm::PreviewMessageModel::updated(const ViewModelEvent& event)
{
	struct RunnableImpl : public Runnable
	{
		RunnableImpl(PreviewMessageModel* pModel) :
			pModel_(pModel)
		{
		}

		virtual void run()
		{
			pModel_->updateToViewModel(!pModel_->bUpdateAlways_);
		}

		PreviewMessageModel* pModel_;
	};
	asyncExec(new RunnableImpl(this));
}

void qm::PreviewMessageModel::viewModelSelected(const ViewModelManagerEvent& event)
{
	killTimer();

	ViewModel* pOldViewModel = getViewModel();
	assert(pOldViewModel == event.getOldViewModel());

	if (pOldViewModel) {
		MessageContext* pContext = getCurrentMessage();
		MessagePtrLock mpl(pContext ? pContext->getMessagePtr() : MessagePtr());
		ViewModel::RestoreInfo info(mpl);
		if (mpl)
			fireUpdateRestoreInfo(&info);
		pOldViewModel->setRestoreInfo(info);
	}

	ViewModel* pNewViewModel = event.getNewViewModel();
	setViewModel(pNewViewModel);
	setCurrentAccount(pViewModelManager_->getCurrentAccount());

	if (pNewViewModel) {
		Lock<ViewModel> lock(*pNewViewModel);
		ViewModel::RestoreInfo info = pNewViewModel->getRestoreInfo();
		MessagePtrLock mpl(info.getMessagePtr());
		if (mpl) {
			setMessage(std::auto_ptr<MessageContext>(
				new MessagePtrMessageContext(mpl)));
			fireApplyRestoreInfo(&info);
		}
		else {
			updateCurrentMessage();
		}
	}
	else {
		clearMessage();
	}
}

void qm::PreviewMessageModel::timerTimeout(Timer::Id nId)
{
	killTimer();
	updateToViewModel(false);
}

void qm::PreviewMessageModel::updateCurrentMessage()
{
	if (bUpdateAlways_)
		updateToViewModel(false);
	else
		clearMessage();
}

MessageViewMode* qm::PreviewMessageModel::getMessageViewMode(ViewModel* pViewModel) const
{
	return pViewModel->getMessageViewMode(ViewModel::MODETYPE_PREVIEW);
}

void qm::PreviewMessageModel::killTimer()
{
	if (!bTimer_)
		return;

	pTimer_->killTimer(TIMER_ITEMSTATECHANGED);
	bTimer_ = false;
}

/****************************************************************************
 *
 * MessageModelHandler
 *
 */

qm::MessageModelHandler::~MessageModelHandler()
{
}

/****************************************************************************
 *
 * MessageModelEvent
 *
 */

qm::MessageModelEvent::MessageModelEvent(const MessageModel* pModel,
										 MessageContext* pContext) :
	pModel_(pModel),
	pContext_(pContext)
{
}

qm::MessageModelEvent::~MessageModelEvent()
{
}

const MessageModel* qm::MessageModelEvent::getMessageModel() const
{
	return pModel_;
}

MessageContext* qm::MessageModelEvent::getMessageContext() const
{
	return pContext_;
}

/****************************************************************************
 *
 * MessageModelRestoreEvent
 *
 */

qm::MessageModelRestoreEvent::MessageModelRestoreEvent(const MessageModel* pModel,
													   ViewModel::RestoreInfo* pRestoreInfo) :
	pModel_(pModel),
	pRestoreInfo_(pRestoreInfo)
{
}

qm::MessageModelRestoreEvent::~MessageModelRestoreEvent()
{
}

const MessageModel* qm::MessageModelRestoreEvent::getMessageModel() const
{
	return pModel_;
}

ViewModel::RestoreInfo* qm::MessageModelRestoreEvent::getRestoreInfo() const
{
	return pRestoreInfo_;
}
<|endoftext|>


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

#include "mbed.h"
#include "us_ticker_api.h"
#include "BLE.h"
#include "wsf_types.h"
#include "wsf_msg.h"
#include "wsf_os.h"
#include "wsf_buf.h"
#include "wsf_timer.h"
#include "hci_handler.h"
#include "dm_handler.h"
#include "l2c_handler.h"
#include "att_handler.h"
#include "smp_handler.h"
#include "l2c_api.h"
#include "att_api.h"
#include "smp_api.h"
#include "hci_drv.h"
#include "CordioBLE.h"
#include "mbed_assert.h"

#include "CordioPalAttClient.h"
#include "CordioPalSecurityManager.h"

/*! WSF handler ID */
wsfHandlerId_t stack_handler_id;

/**
 * Weak definition of ble_cordio_get_hci_driver.
 * A runtime error is generated if the user does not define any
 * ble_cordio_get_hci_driver.
 */
MBED_WEAK ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver()
{
    error("Please provide an implementation for the HCI driver");
    ble::vendor::cordio::CordioHCIDriver* bad_instance = NULL;
    return *bad_instance;
}

/**
 * Low level HCI interface between Cordio stack and the port.
 */
extern "C" uint16_t hci_mbed_os_drv_write(uint8_t type, uint16_t len, uint8_t *pData)
{
    return ble_cordio_get_hci_driver().write(type, len, pData);
}

extern "C" void hci_mbed_os_start_reset_sequence(void)
{
    ble_cordio_get_hci_driver().start_reset_sequence();
}

extern "C" void hci_mbed_os_handle_reset_sequence(uint8_t* msg)
{
     ble_cordio_get_hci_driver().handle_reset_sequence(msg);
}

/*
 * This function will signal to the user code by calling signalEventsToProcess.
 * It is registered and called into the Wsf Stack.
 */
extern "C" void wsf_mbed_ble_signal_event(void)
{
    ble::vendor::cordio::BLE::deviceInstance().signalEventsToProcess(::BLE::DEFAULT_INSTANCE);
}

/**
 * BLE-API requires an implementation of the following function in order to
 * obtain its transport handle.
 */
BLEInstanceBase *createBLEInstance()
{
    return (&(ble::vendor::cordio::BLE::deviceInstance()));
}

namespace ble {
namespace vendor {
namespace cordio {

BLE::BLE(CordioHCIDriver& hci_driver) :
    initialization_status(NOT_INITIALIZED),
    instanceID(::BLE::DEFAULT_INSTANCE),
    _event_queue()
{
    _hci_driver = &hci_driver;
    stack_setup();
}

BLE::~BLE() { }

/**
 * The singleton which represents the BLE transport for the BLE.
 */
BLE& BLE::deviceInstance()
{
    static BLE instance(
        ble_cordio_get_hci_driver()
    );
    return instance;
}

ble_error_t BLE::init(
    ::BLE::InstanceID_t instanceID,
    FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext *> initCallback)
{
    switch (initialization_status) {
        case NOT_INITIALIZED:
            _event_queue.initialize(this, instanceID);
            _init_callback = initCallback;
            start_stack_reset();
            return BLE_ERROR_NONE;

        case INITIALIZING:
            return BLE_ERROR_INITIALIZATION_INCOMPLETE;

        case INITIALIZED:
            return BLE_ERROR_NONE;

        default:
            return BLE_ERROR_UNSPECIFIED;
    }
}

bool BLE::hasInitialized() const
{
    return initialization_status == INITIALIZED;
}

ble_error_t BLE::shutdown()
{
    if (initialization_status != INITIALIZED) {
        return BLE_ERROR_INITIALIZATION_INCOMPLETE;
    }

    initialization_status = NOT_INITIALIZED;
    _hci_driver->terminate();

    getGattServer().reset();
    getGattClient().reset();
    getGap().reset();
    _event_queue.clear();

    return BLE_ERROR_NONE;
}

const char* BLE::getVersion()
{
    static const char version[] = "generic-cordio";
    return version;
}

generic::GenericGap& BLE::getGap()
{
    return const_cast<generic::GenericGap&>(getGap());
}

const generic::GenericGap& BLE::getGap() const
{
    static pal::vendor::cordio::Gap& cordio_pal_gap =
        pal::vendor::cordio::Gap::get_gap();
    static pal::vendor::cordio::GenericAccessService cordio_gap_service;
    static ble::generic::GenericGap gap(
        _event_queue,
        cordio_pal_gap,
        cordio_gap_service
    );
    return gap;
};

GattServer& BLE::getGattServer()
{
    return cordio::GattServer::getInstance();
}

const GattServer& BLE::getGattServer() const
{
    return cordio::GattServer::getInstance();
}

generic::GenericGattClient& BLE::getGattClient()
{
    static pal::AttClientToGattClientAdapter pal_client(
        pal::vendor::cordio::CordioAttClient::get_client()
    );
    static generic::GenericGattClient client(&pal_client);

    return client;
}

SecurityManager& BLE::getSecurityManager()
{
    return const_cast<SecurityManager&>(getSecurityManager());
}

const SecurityManager& BLE::getSecurityManager() const
{
    static pal::MemorySecurityDb m_db;
    pal::vendor::cordio::CordioSecurityManager &m_pal = pal::vendor::cordio::CordioSecurityManager::get_security_manager();

    BLE &self = const_cast<BLE&>(*this);

    static SigningEventMonitorProxy signing_event_monitor(self);

    static generic::GenericSecurityManager m_instance(
        m_pal,
        m_db,
        self.getGap(),
        signing_event_monitor
    );

    return m_instance;
}

void BLE::waitForEvent()
{
    static Timeout nextTimeout;
    timestamp_t nextTimestamp;
    bool_t pTimerRunning;

    callDispatcher();

    if (wsfOsReadyToSleep()) {
        // setup an mbed timer for the next cordio timeout
        nextTimestamp = (timestamp_t)(WsfTimerNextExpiration(&pTimerRunning) * WSF_MS_PER_TICK) * 1000;
        if (pTimerRunning) {
            nextTimeout.attach_us(timeoutCallback, nextTimestamp);
        }
    }
}

void BLE::processEvents()
{
    callDispatcher();
}

 void BLE::stack_handler(wsfEventMask_t event, wsfMsgHdr_t* msg)
 {
    if (msg == NULL) {
        return;
    }

    if (ble::pal::vendor::cordio::CordioSecurityManager::get_security_manager().sm_handler(msg)) {
        return;
    }

    switch(msg->event) {
        case DM_RESET_CMPL_IND: {
            ::BLE::InitializationCompleteCallbackContext context = {
                ::BLE::Instance(::BLE::DEFAULT_INSTANCE),
                BLE_ERROR_NONE
            };
            deviceInstance().getGattServer().initialize();
            deviceInstance().initialization_status = INITIALIZED;
            _init_callback.call(&context);
        }   break;

        default:
            ble::pal::vendor::cordio::Gap::gap_handler(msg);
            break;
    }
}

void BLE::device_manager_cb(dmEvt_t* dm_event)
{
    BLE::deviceInstance().stack_handler(0, &dm_event->hdr);
}

/*
 * AttServerInitDeInitCback callback is used to Initialize/Deinitialize
 * the CCC Table of the ATT Server when a remote peer requests to Open
 * or Close the connection.
 */
 void BLE::connection_handler(dmEvt_t* dm_event)
 {
    dmConnId_t connId = (dmConnId_t)dm_event->hdr.param;

    switch (dm_event->hdr.event) {
        case DM_CONN_OPEN_IND:
            /* set up CCC table with uninitialized (all zero) values */
            AttsCccInitTable(connId, NULL);
            break;
        case DM_CONN_CLOSE_IND:
            /* clear CCC table on connection close */
            AttsCccClearTable(connId);
            break;
        default:
            break;
    }
}

void BLE::timeoutCallback()
{
    wsf_mbed_ble_signal_event();
}

void BLE::stack_setup()
{
    MBED_ASSERT(_hci_driver != NULL);

    wsfHandlerId_t handlerId;

    buf_pool_desc_t buf_pool_desc = _hci_driver->get_buffer_pool_description();

    // Initialize buffers with the ones provided by the HCI driver
    uint16_t bytes_used = WsfBufInit(
        buf_pool_desc.buffer_size, buf_pool_desc.buffer_memory,
        buf_pool_desc.pool_count, buf_pool_desc.pool_description
    );

    MBED_ASSERT(bytes_used != 0);

    WsfTimerInit();
    SecInit();

    // Note: enable once security is supported
    SecRandInit();
    SecAesInit();
    SecCmacInit();
    SecEccInit();

    handlerId = WsfOsSetNextHandler(HciHandler);
    HciHandlerInit(handlerId);

    handlerId = WsfOsSetNextHandler(DmHandler);
    DmAdvInit();
    DmScanInit();
    DmConnInit();
    DmConnMasterInit();
    DmConnSlaveInit();
    DmSecInit();

    // Note: enable once security is supported
    DmSecLescInit();
    DmPrivInit();
    DmHandlerInit(handlerId);

    handlerId = WsfOsSetNextHandler(L2cSlaveHandler);
    L2cSlaveHandlerInit(handlerId);
    L2cInit();
    L2cSlaveInit();
    L2cMasterInit();

    handlerId = WsfOsSetNextHandler(AttHandler);
    AttHandlerInit(handlerId);
    AttsInit();
    AttsIndInit();
    AttcInit();

    handlerId = WsfOsSetNextHandler(SmpHandler);
    SmpHandlerInit(handlerId);
    SmprInit();
    SmprScInit();
    SmpiInit();
    SmpiScInit();

    stack_handler_id = WsfOsSetNextHandler(&BLE::stack_handler);

    HciSetMaxRxAclLen(100);

    DmRegister(BLE::device_manager_cb);
    DmConnRegister(DM_CLIENT_ID_APP, BLE::device_manager_cb);
    AttConnRegister(BLE::connection_handler);
    AttRegister((attCback_t) ble::pal::vendor::cordio::CordioAttClient::att_client_handler);
}

void BLE::start_stack_reset()
{
    _hci_driver->initialize();
    DmDevReset();
}

void BLE::callDispatcher()
{
    // process the external event queue
    _event_queue.process();

    // follow by stack events
    static uint32_t lastTimeUs = us_ticker_read();
    uint32_t currTimeUs, deltaTimeMs;

    // Update the current cordio time
    currTimeUs = us_ticker_read();
    deltaTimeMs = (currTimeUs - lastTimeUs) / 1000;
    if (deltaTimeMs > 0) {
        WsfTimerUpdate(deltaTimeMs / WSF_MS_PER_TICK);
        lastTimeUs += deltaTimeMs * 1000;
    }

    wsfOsDispatcher();

    if (wsfOsReadyToSleep()) {
        static Timeout nextTimeout;
        // setup an mbed timer for the next Cordio timeout
        bool_t pTimerRunning;
        timestamp_t nextTimestamp = (timestamp_t) (WsfTimerNextExpiration(&pTimerRunning) * WSF_MS_PER_TICK) * 1000;
        if (pTimerRunning) {
            nextTimeout.attach_us(timeoutCallback, nextTimestamp);
        }
    }
}

CordioHCIDriver* BLE::_hci_driver = NULL;

FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext*> BLE::_init_callback;

} // namespace cordio
} // namespace vendor
} // namespace ble
<commit_msg>fix const induced recursive call<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2017-2017 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mbed.h"
#include "us_ticker_api.h"
#include "BLE.h"
#include "wsf_types.h"
#include "wsf_msg.h"
#include "wsf_os.h"
#include "wsf_buf.h"
#include "wsf_timer.h"
#include "hci_handler.h"
#include "dm_handler.h"
#include "l2c_handler.h"
#include "att_handler.h"
#include "smp_handler.h"
#include "l2c_api.h"
#include "att_api.h"
#include "smp_api.h"
#include "hci_drv.h"
#include "CordioBLE.h"
#include "mbed_assert.h"

#include "CordioPalAttClient.h"
#include "CordioPalSecurityManager.h"

/*! WSF handler ID */
wsfHandlerId_t stack_handler_id;

/**
 * Weak definition of ble_cordio_get_hci_driver.
 * A runtime error is generated if the user does not define any
 * ble_cordio_get_hci_driver.
 */
MBED_WEAK ble::vendor::cordio::CordioHCIDriver& ble_cordio_get_hci_driver()
{
    error("Please provide an implementation for the HCI driver");
    ble::vendor::cordio::CordioHCIDriver* bad_instance = NULL;
    return *bad_instance;
}

/**
 * Low level HCI interface between Cordio stack and the port.
 */
extern "C" uint16_t hci_mbed_os_drv_write(uint8_t type, uint16_t len, uint8_t *pData)
{
    return ble_cordio_get_hci_driver().write(type, len, pData);
}

extern "C" void hci_mbed_os_start_reset_sequence(void)
{
    ble_cordio_get_hci_driver().start_reset_sequence();
}

extern "C" void hci_mbed_os_handle_reset_sequence(uint8_t* msg)
{
     ble_cordio_get_hci_driver().handle_reset_sequence(msg);
}

/*
 * This function will signal to the user code by calling signalEventsToProcess.
 * It is registered and called into the Wsf Stack.
 */
extern "C" void wsf_mbed_ble_signal_event(void)
{
    ble::vendor::cordio::BLE::deviceInstance().signalEventsToProcess(::BLE::DEFAULT_INSTANCE);
}

/**
 * BLE-API requires an implementation of the following function in order to
 * obtain its transport handle.
 */
BLEInstanceBase *createBLEInstance()
{
    return (&(ble::vendor::cordio::BLE::deviceInstance()));
}

namespace ble {
namespace vendor {
namespace cordio {

BLE::BLE(CordioHCIDriver& hci_driver) :
    initialization_status(NOT_INITIALIZED),
    instanceID(::BLE::DEFAULT_INSTANCE),
    _event_queue()
{
    _hci_driver = &hci_driver;
    stack_setup();
}

BLE::~BLE() { }

/**
 * The singleton which represents the BLE transport for the BLE.
 */
BLE& BLE::deviceInstance()
{
    static BLE instance(
        ble_cordio_get_hci_driver()
    );
    return instance;
}

ble_error_t BLE::init(
    ::BLE::InstanceID_t instanceID,
    FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext *> initCallback)
{
    switch (initialization_status) {
        case NOT_INITIALIZED:
            _event_queue.initialize(this, instanceID);
            _init_callback = initCallback;
            start_stack_reset();
            return BLE_ERROR_NONE;

        case INITIALIZING:
            return BLE_ERROR_INITIALIZATION_INCOMPLETE;

        case INITIALIZED:
            return BLE_ERROR_NONE;

        default:
            return BLE_ERROR_UNSPECIFIED;
    }
}

bool BLE::hasInitialized() const
{
    return initialization_status == INITIALIZED;
}

ble_error_t BLE::shutdown()
{
    if (initialization_status != INITIALIZED) {
        return BLE_ERROR_INITIALIZATION_INCOMPLETE;
    }

    initialization_status = NOT_INITIALIZED;
    _hci_driver->terminate();

    getGattServer().reset();
    getGattClient().reset();
    getGap().reset();
    _event_queue.clear();

    return BLE_ERROR_NONE;
}

const char* BLE::getVersion()
{
    static const char version[] = "generic-cordio";
    return version;
}

generic::GenericGap& BLE::getGap()
{
    const BLE &const_self = const_cast<const BLE&>(*this);
    return const_cast<generic::GenericGap&>(const_self.getGap());
}

const generic::GenericGap& BLE::getGap() const
{
    static pal::vendor::cordio::Gap& cordio_pal_gap =
        pal::vendor::cordio::Gap::get_gap();
    static pal::vendor::cordio::GenericAccessService cordio_gap_service;
    static ble::generic::GenericGap gap(
        _event_queue,
        cordio_pal_gap,
        cordio_gap_service
    );
    return gap;
};

GattServer& BLE::getGattServer()
{
    return cordio::GattServer::getInstance();
}

const GattServer& BLE::getGattServer() const
{
    return cordio::GattServer::getInstance();
}

generic::GenericGattClient& BLE::getGattClient()
{
    static pal::AttClientToGattClientAdapter pal_client(
        pal::vendor::cordio::CordioAttClient::get_client()
    );
    static generic::GenericGattClient client(&pal_client);

    return client;
}

SecurityManager& BLE::getSecurityManager()
{
    const BLE &const_self = const_cast<const BLE&>(*this);
    return const_cast<SecurityManager&>(const_self.getSecurityManager());
}

const SecurityManager& BLE::getSecurityManager() const
{
    static pal::MemorySecurityDb m_db;
    pal::vendor::cordio::CordioSecurityManager &m_pal = pal::vendor::cordio::CordioSecurityManager::get_security_manager();

    BLE &self = const_cast<BLE&>(*this);

    static SigningEventMonitorProxy signing_event_monitor(self);

    static generic::GenericSecurityManager m_instance(
        m_pal,
        m_db,
        self.getGap(),
        signing_event_monitor
    );

    return m_instance;
}

void BLE::waitForEvent()
{
    static Timeout nextTimeout;
    timestamp_t nextTimestamp;
    bool_t pTimerRunning;

    callDispatcher();

    if (wsfOsReadyToSleep()) {
        // setup an mbed timer for the next cordio timeout
        nextTimestamp = (timestamp_t)(WsfTimerNextExpiration(&pTimerRunning) * WSF_MS_PER_TICK) * 1000;
        if (pTimerRunning) {
            nextTimeout.attach_us(timeoutCallback, nextTimestamp);
        }
    }
}

void BLE::processEvents()
{
    callDispatcher();
}

 void BLE::stack_handler(wsfEventMask_t event, wsfMsgHdr_t* msg)
 {
    if (msg == NULL) {
        return;
    }

    if (ble::pal::vendor::cordio::CordioSecurityManager::get_security_manager().sm_handler(msg)) {
        return;
    }

    switch(msg->event) {
        case DM_RESET_CMPL_IND: {
            ::BLE::InitializationCompleteCallbackContext context = {
                ::BLE::Instance(::BLE::DEFAULT_INSTANCE),
                BLE_ERROR_NONE
            };
            deviceInstance().getGattServer().initialize();
            deviceInstance().initialization_status = INITIALIZED;
            _init_callback.call(&context);
        }   break;

        default:
            ble::pal::vendor::cordio::Gap::gap_handler(msg);
            break;
    }
}

void BLE::device_manager_cb(dmEvt_t* dm_event)
{
    BLE::deviceInstance().stack_handler(0, &dm_event->hdr);
}

/*
 * AttServerInitDeInitCback callback is used to Initialize/Deinitialize
 * the CCC Table of the ATT Server when a remote peer requests to Open
 * or Close the connection.
 */
 void BLE::connection_handler(dmEvt_t* dm_event)
 {
    dmConnId_t connId = (dmConnId_t)dm_event->hdr.param;

    switch (dm_event->hdr.event) {
        case DM_CONN_OPEN_IND:
            /* set up CCC table with uninitialized (all zero) values */
            AttsCccInitTable(connId, NULL);
            break;
        case DM_CONN_CLOSE_IND:
            /* clear CCC table on connection close */
            AttsCccClearTable(connId);
            break;
        default:
            break;
    }
}

void BLE::timeoutCallback()
{
    wsf_mbed_ble_signal_event();
}

void BLE::stack_setup()
{
    MBED_ASSERT(_hci_driver != NULL);

    wsfHandlerId_t handlerId;

    buf_pool_desc_t buf_pool_desc = _hci_driver->get_buffer_pool_description();

    // Initialize buffers with the ones provided by the HCI driver
    uint16_t bytes_used = WsfBufInit(
        buf_pool_desc.buffer_size, buf_pool_desc.buffer_memory,
        buf_pool_desc.pool_count, buf_pool_desc.pool_description
    );

    MBED_ASSERT(bytes_used != 0);

    WsfTimerInit();
    SecInit();

    // Note: enable once security is supported
    SecRandInit();
    SecAesInit();
    SecCmacInit();
    SecEccInit();

    handlerId = WsfOsSetNextHandler(HciHandler);
    HciHandlerInit(handlerId);

    handlerId = WsfOsSetNextHandler(DmHandler);
    DmAdvInit();
    DmScanInit();
    DmConnInit();
    DmConnMasterInit();
    DmConnSlaveInit();
    DmSecInit();

    // Note: enable once security is supported
    DmSecLescInit();
    DmPrivInit();
    DmHandlerInit(handlerId);

    handlerId = WsfOsSetNextHandler(L2cSlaveHandler);
    L2cSlaveHandlerInit(handlerId);
    L2cInit();
    L2cSlaveInit();
    L2cMasterInit();

    handlerId = WsfOsSetNextHandler(AttHandler);
    AttHandlerInit(handlerId);
    AttsInit();
    AttsIndInit();
    AttcInit();

    handlerId = WsfOsSetNextHandler(SmpHandler);
    SmpHandlerInit(handlerId);
    SmprInit();
    SmprScInit();
    SmpiInit();
    SmpiScInit();

    stack_handler_id = WsfOsSetNextHandler(&BLE::stack_handler);

    HciSetMaxRxAclLen(100);

    DmRegister(BLE::device_manager_cb);
    DmConnRegister(DM_CLIENT_ID_APP, BLE::device_manager_cb);
    AttConnRegister(BLE::connection_handler);
    AttRegister((attCback_t) ble::pal::vendor::cordio::CordioAttClient::att_client_handler);
}

void BLE::start_stack_reset()
{
    _hci_driver->initialize();
    DmDevReset();
}

void BLE::callDispatcher()
{
    // process the external event queue
    _event_queue.process();

    // follow by stack events
    static uint32_t lastTimeUs = us_ticker_read();
    uint32_t currTimeUs, deltaTimeMs;

    // Update the current cordio time
    currTimeUs = us_ticker_read();
    deltaTimeMs = (currTimeUs - lastTimeUs) / 1000;
    if (deltaTimeMs > 0) {
        WsfTimerUpdate(deltaTimeMs / WSF_MS_PER_TICK);
        lastTimeUs += deltaTimeMs * 1000;
    }

    wsfOsDispatcher();

    if (wsfOsReadyToSleep()) {
        static Timeout nextTimeout;
        // setup an mbed timer for the next Cordio timeout
        bool_t pTimerRunning;
        timestamp_t nextTimestamp = (timestamp_t) (WsfTimerNextExpiration(&pTimerRunning) * WSF_MS_PER_TICK) * 1000;
        if (pTimerRunning) {
            nextTimeout.attach_us(timeoutCallback, nextTimestamp);
        }
    }
}

CordioHCIDriver* BLE::_hci_driver = NULL;

FunctionPointerWithContext< ::BLE::InitializationCompleteCallbackContext*> BLE::_init_callback;

} // namespace cordio
} // namespace vendor
} // namespace ble
<|endoftext|>


<commit_before>#include "litesql-gen-wxformbuilder.hpp"

#include <fstream>

using namespace std;
using namespace xml;
using namespace litesql;

const char* wxFormBuilderGenerator::NAME = "wxFormBuilder";

wxFormBuilderGenerator::wxFormBuilderGenerator()
    : CodeGenerator(NAME)
{ }

void wxFormBuilderGenerator::setOutputFilename(const std::string& filename)
{
    m_outputFilename=filename;
}

static bool generateFieldUI(const xml::Field::Ptr& field,ostream& os,size_t indent)
{
    os  << "                <object class=\"sizeritem\" expanded=\"1\">" << endl
        << "                    <property name=\"border\">5</property>" << endl
        << "                    <property name=\"flag\">wxALL|wxEXPAND</property>" << endl
        << "                    <property name=\"proportion\">1</property>" << endl
        << "                    <object class=\"wxStaticText\" expanded=\"1\">" << endl
        << "                        <property name=\"bg\" />" << endl
        << "                        <property name=\"context_help\" />" << endl
        << "                        <property name=\"enabled\">1</property>" << endl
        << "                        <property name=\"fg\" />" << endl
        << "                        <property name=\"font\" />" << endl
        << "                        <property name=\"hidden\">0</property>" << endl
        << "                        <property name=\"id\">wxID_ANY</property>" << endl
        << "                        <property name=\"label\">" << capitalize(field->name)    << "</property>" << endl
        << "                        <property name=\"maximum_size\" />" << endl
        << "                        <property name=\"minimum_size\" />" << endl
        << "                        <property name=\"name\">lbl_" << capitalize(field->name) << "</property>" << endl
        << "                        <property name=\"permission\">protected</property>" << endl
        << "                        <property name=\"pos\" />" << endl
        << "                        <property name=\"size\" />" << endl
        << "                        <property name=\"style\" />" << endl
        << "                        <property name=\"subclass\" />" << endl
        << "                        <property name=\"tooltip\" />" << endl
        << "                        <property name=\"window_extra_style\" />" << endl
        << "                        <property name=\"window_name\" />" << endl
        << "                        <property name=\"window_style\" />" << endl
        << "                        <property name=\"wrap\">-1</property>" << endl
        << "                        <event name=\"OnChar\" />" << endl
        << "                        <event name=\"OnEnterWindow\" />" << endl
        << "                        <event name=\"OnEraseBackground\" />" << endl
        << "                        <event name=\"OnKeyDown\" />" << endl
        << "                        <event name=\"OnKeyUp\" />" << endl
        << "                        <event name=\"OnKillFocus\" />" << endl
        << "                        <event name=\"OnLeaveWindow\" />" << endl
        << "                        <event name=\"OnLeftDClick\" />" << endl
        << "                        <event name=\"OnLeftDown\" />" << endl
        << "                        <event name=\"OnLeftUp\" />" << endl
        << "                        <event name=\"OnMiddleDClick\" />" << endl
        << "                        <event name=\"OnMiddleDown\" />" << endl
        << "                        <event name=\"OnMiddleUp\" />" << endl
        << "                        <event name=\"OnMotion\" />" << endl
        << "                        <event name=\"OnMouseEvents\" />" << endl
        << "                        <event name=\"OnMouseWheel\" />" << endl
        << "                        <event name=\"OnPaint\" />" << endl
        << "                        <event name=\"OnRightDClick\" />" << endl
        << "                        <event name=\"OnRightDown\" />" << endl
        << "                        <event name=\"OnRightUp\" />" << endl
        << "                        <event name=\"OnSetFocus\" />" << endl
        << "                        <event name=\"OnSize\" />" << endl
        << "                        <event name=\"OnUpdateUI\" />" << endl
        << "                    </object>" << endl
        << "                </object>" << endl
        << "                <object class=\"sizeritem\" expanded=\"1\">" << endl
        << "                    <property name=\"border\">5</property>" << endl
        << "                    <property name=\"flag\">wxALL|wxFIXED_MINSIZE|wxEXPAND</property>" << endl
        << "                    <property name=\"proportion\">2</property>" << endl;
        switch(field->type)
        {
            case A_field_type_boolean:
                os << "                    <object class=\"wxCheckBox\" expanded=\"1\">" << endl;
                break;

            case A_field_type_date:
            case A_field_type_datetime:
            case A_field_type_time:

            case A_field_type_string:
            default:
                os << "                    <object class=\"wxTextCtrl\" expanded=\"1\">" << endl;
        }

        os << "                        <property name=\"bg\" />" << endl
        << "                        <property name=\"context_help\" />" << endl
        << "                        <property name=\"enabled\">1</property>" << endl
        << "                        <property name=\"fg\" />" << endl
        << "                        <property name=\"font\" />" << endl
        << "                        <property name=\"hidden\">0</property>" << endl
        << "                        <property name=\"id\">wxID_ANY</property>" << endl
        << "                        <property name=\"maximum_size\" />" << endl
        << "                        <property name=\"maxlength\">0</property>" << endl
        << "                        <property name=\"minimum_size\">-1,-1</property>" << endl
        << "                        <property name=\"name\">m_textCtrl_" << capitalize(field->name) << "</property>" << endl
        << "                        <property name=\"permission\">protected</property>" << endl
        << "                        <property name=\"pos\" />" << endl
        << "                        <property name=\"size\" />" << endl
        << "                        <property name=\"style\" />" << endl
        << "                        <property name=\"subclass\" />" << endl
        << "                        <property name=\"tooltip\" />" << endl
        << "                        <property name=\"value\" />" << endl
        << "                        <property name=\"window_extra_style\" />" << endl
        << "                        <property name=\"window_name\" />" << endl
        << "                        <property name=\"window_style\" />" << endl
        << "                        <event name=\"OnChar\" />" << endl
        << "                        <event name=\"OnEnterWindow\" />" << endl
        << "                        <event name=\"OnEraseBackground\" />" << endl
        << "                        <event name=\"OnKeyDown\" />" << endl
        << "                        <event name=\"OnKeyUp\" />" << endl
        << "                        <event name=\"OnKillFocus\" />" << endl
        << "                        <event name=\"OnLeaveWindow\" />" << endl
        << "                        <event name=\"OnLeftDClick\" />" << endl
        << "                        <event name=\"OnLeftDown\" />" << endl
        << "                        <event name=\"OnLeftUp\" />" << endl
        << "                        <event name=\"OnMiddleDClick\" />" << endl
        << "                        <event name=\"OnMiddleDown\" />" << endl
        << "                        <event name=\"OnMiddleUp\" />" << endl
        << "                        <event name=\"OnMotion\" />" << endl
        << "                        <event name=\"OnMouseEvents\" />" << endl
        << "                        <event name=\"OnMouseWheel\" />" << endl
        << "                        <event name=\"OnPaint\" />" << endl
        << "                        <event name=\"OnRightDClick\" />" << endl
        << "                        <event name=\"OnRightDown\" />" << endl
        << "                        <event name=\"OnRightUp\" />" << endl
        << "                        <event name=\"OnSetFocus\" />" << endl
        << "                        <event name=\"OnSize\" />" << endl
        << "                        <event name=\"OnText\" />" << endl
        << "                        <event name=\"OnTextEnter\" />" << endl
        << "                        <event name=\"OnTextMaxLen\" />" << endl
        << "                        <event name=\"OnTextURL\" />" << endl
        << "                        <event name=\"OnUpdateUI\" />" << endl
        << "                    </object>" << endl
        << "                </object>" << endl;
    return true;
}

static bool generateDetailPanel(const xml::ObjectPtr& object,ostream& os,size_t indent)
{
    os << "      <object class=\"Panel\" expanded=\"0\">" << endl
        << "            <property name=\"bg\" />" << endl
        << "            <property name=\"context_help\" />" << endl
        << "            <property name=\"enabled\">1</property>" << endl
        << "            <property name=\"fg\" />" << endl
        << "            <property name=\"font\" />" << endl
        << "            <property name=\"hidden\">0</property>" << endl
        << "            <property name=\"id\">wxID_ANY</property>" << endl
        << "            <property name=\"maximum_size\" />" << endl
        << "            <property name=\"minimum_size\">250,80</property>" << endl
        << "            <property name=\"name\">" << object->name << "Panel</property>" << endl
        << "            <property name=\"pos\" />" << endl
        << "            <property name=\"size\">" << object->fields.size() *15 << ",80</property>" << endl
        << "            <property name=\"subclass\" />" << endl
        << "            <property name=\"tooltip\" />" << endl
        << "            <property name=\"window_extra_style\" />" << endl
        << "            <property name=\"window_name\" />" << endl
        << "            <property name=\"window_style\">wxTAB_TRAVERSAL</property>" << endl
        << "            <event name=\"OnChar\" />" << endl
        << "            <event name=\"OnEnterWindow\" />" << endl
        << "            <event name=\"OnEraseBackground\" />" << endl
        << "            <event name=\"OnInitDialog\" />" << endl
        << "            <event name=\"OnKeyDown\" />" << endl
        << "            <event name=\"OnKeyUp\" />" << endl
        << "            <event name=\"OnKillFocus\" />" << endl
        << "            <event name=\"OnLeaveWindow\" />" << endl
        << "            <event name=\"OnLeftDClick\" />" << endl
        << "            <event name=\"OnLeftDown\" />" << endl
        << "            <event name=\"OnLeftUp\" />" << endl
        << "            <event name=\"OnMiddleDClick\" />" << endl
        << "            <event name=\"OnMiddleDown\" />" << endl
        << "            <event name=\"OnMiddleUp\" />" << endl
        << "            <event name=\"OnMotion\" />" << endl
        << "            <event name=\"OnMouseEvents\" />" << endl
        << "            <event name=\"OnMouseWheel\" />" << endl
        << "            <event name=\"OnPaint\" />" << endl
        << "            <event name=\"OnRightDClick\" />" << endl
        << "            <event name=\"OnRightDown\" />" << endl
        << "            <event name=\"OnRightUp\" />" << endl
        << "            <event name=\"OnSetFocus\" />" << endl
        << "            <event name=\"OnSize\" />" << endl
        << "            <event name=\"OnUpdateUI\" />" << endl
        << "            <object class=\"wxFlexGridSizer\" expanded=\"1\">" << endl
        << "                <property name=\"cols\">2</property>" << endl
        << "                <property name=\"flexible_direction\">wxBOTH</property>" << endl
        << "                <property name=\"growablecols\">1</property>" << endl
        << "                <property name=\"growablerows\" />" << endl
        << "                <property name=\"hgap\">0</property>" << endl
        << "                <property name=\"minimum_size\" />" << endl
        << "                <property name=\"name\">gSizer1</property>" << endl
        << "                <property name=\"non_flexible_grow_mode\">wxFLEX_GROWMODE_SPECIFIED</property>" << endl
        << "                <property name=\"permission\">none</property>" << endl
        << "                <property name=\"rows\">" << object->fields.size()<< "</property>" << endl
        << "                <property name=\"vgap\">0</property>" << endl;

    for (Field::sequence::const_iterator field_it = object->fields.begin();
        field_it != object->fields.end();
        field_it++)
    {
        if (((*field_it)->name!="id") && ((*field_it)->name!="type"))
        {
            generateFieldUI(*field_it,os,indent);
        }
    }

    os  << "           </object>" << endl
        << "        </object>" << endl;

    return true;
}

bool wxFormBuilderGenerator::generate(const xml::ObjectPtr& object,ostream& os,size_t indent)
{
    generateDetailPanel(object,os,indent);
//    generateListPanel(object,os,indent);

    return true;
}

bool wxFormBuilderGenerator::generate(const Relation::Ptr &  relation,ostream& os,size_t indent)
{
    return true;
}

bool wxFormBuilderGenerator::generateCode(const ObjectModel* model)
{
    bool success;
    string ofname =   m_outputFilename.empty()
        ?  model->db->name +".fbp"
        :  m_outputFilename;

    ofstream ofs(getOutputFilename(ofname).c_str());

    ofs << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>" << endl
        << "<wxFormBuilder_Project>" << endl
        << "    <FileVersion major=\"1\" minor=\"10\" />" << endl
        << "    <object class=\"Project\" expanded=\"1\">" << endl
        << "        <property name=\"class_decoration\" />" << endl
        << "        <property name=\"code_generation\">C++</property>" << endl
        << "        <property name=\"disconnect_events\">1</property>" << endl
        << "        <property name=\"encoding\">UTF-8</property>" << endl
        << "        <property name=\"event_generation\">connect</property>" << endl
        << "        <property name=\"file\">ui</property>" << endl
        << "        <property name=\"first_id\">1000</property>" << endl
        << "        <property name=\"help_provider\">wxHelpControllerHelpProvider</property>" << endl
        << "        <property name=\"internationalize\">1</property>" << endl
        << "        <property name=\"name\">Litesql</property>" << endl
        << "        <property name=\"namespace\">"ui"</property>" << endl
        << "        <property name=\"path\">../</property>" << endl
        << "        <property name=\"precompiled_header\" />" << endl
        << "        <property name=\"relative_path\">1</property>" << endl
        << "        <property name=\"use_enum\">1</property>" << endl
        << "        <property name=\"use_microsoft_bom\">0</property>" << endl;

    success = CodeGenerator::generate(model->objects,ofs,2);
    success &= CodeGenerator::generate(model->relations,ofs,2);

    ofs << "    </object>" << endl
        << "</wxFormBuilder_Project>" << endl;
    ofs.close();
    return success;
}

<commit_msg>specialized ui-elements for bool (checkbox), int (SpinCtrl) and date (wxDatePicker)<commit_after>#include "litesql-gen-wxformbuilder.hpp"

#include <fstream>

using namespace std;
using namespace xml;
using namespace litesql;

const char* wxFormBuilderGenerator::NAME = "wxFormBuilder";

wxFormBuilderGenerator::wxFormBuilderGenerator()
    : CodeGenerator(NAME)
{ }

void wxFormBuilderGenerator::setOutputFilename(const std::string& filename)
{
    m_outputFilename=filename;
}

static bool generateFieldUI(const xml::Field::Ptr& field,ostream& os,size_t indent)
{
    os  << "                <object class=\"sizeritem\" expanded=\"1\">" << endl
        << "                    <property name=\"border\">5</property>" << endl
        << "                    <property name=\"flag\">wxALL|wxEXPAND</property>" << endl
        << "                    <property name=\"proportion\">1</property>" << endl
        << "                    <object class=\"wxStaticText\" expanded=\"1\">" << endl
        << "                        <property name=\"label\">" << capitalize(field->name)    << "</property>" << endl
        << "                        <property name=\"name\">lbl_" << capitalize(field->name) << "</property>" << endl
        << "                    </object>" << endl
        << "                </object>" << endl
        << "                <object class=\"sizeritem\" expanded=\"1\">" << endl
        << "                    <property name=\"border\">5</property>" << endl
        << "                    <property name=\"flag\">wxALL|wxFIXED_MINSIZE|wxEXPAND</property>" << endl
        << "                    <property name=\"proportion\">2</property>" << endl;
        switch(field->type)
        {
            case A_field_type_boolean:
                os << "                    <object class=\"wxCheckBox\" expanded=\"1\">" << endl;
                break;
            case A_field_type_integer:
                os << "                    <object class=\"wxSpinCtrl\" expanded=\"1\">" << endl
                   << "                        <property name=\"name\">m_spin_" << capitalize(field->name) << "</property>" << endl;
          break;

            case A_field_type_date:
                os << "                    <object class=\"wxDatePickerCtrl\" expanded=\"1\">" << endl
                   << "                        <property name=\"name\">m_datePicker_" << capitalize(field->name) << "</property>" << endl;

                break;

            case A_field_type_datetime:
            case A_field_type_time:

            case A_field_type_string:
            default:
                os << "                    <object class=\"wxTextCtrl\" expanded=\"1\">"  << endl
                   << "                        <property name=\"maxlength\">0</property>" << endl
                   << "                        <property name=\"name\">m_textCtrl_" << capitalize(field->name) << "</property>" << endl;
        }

        os  << "                    </object>" << endl
            << "                </object>" << endl;
    return true;
}

static bool generateDetailPanel(const xml::ObjectPtr& object,ostream& os,size_t indent)
{
    os << "      <object class=\"Panel\" expanded=\"0\">" << endl
        << "            <property name=\"minimum_size\">280,80</property>" << endl
        << "            <property name=\"name\">" << object->name << "Panel</property>" << endl
        << "            <property name=\"pos\" />" << endl
        << "            <property name=\"size\">280," << object->fields.size() * 20 << "</property>" << endl
        << "            <object class=\"wxFlexGridSizer\" expanded=\"1\">" << endl
        << "                <property name=\"cols\">2</property>" << endl
        << "                <property name=\"flexible_direction\">wxBOTH</property>" << endl
        << "                <property name=\"growablecols\">1</property>" << endl
        << "                <property name=\"growablerows\" />" << endl
        << "                <property name=\"hgap\">0</property>" << endl
        << "                <property name=\"minimum_size\" />" << endl
        << "                <property name=\"name\">gFieldSizer</property>" << endl
        << "                <property name=\"non_flexible_grow_mode\">wxFLEX_GROWMODE_SPECIFIED</property>" << endl
        << "                <property name=\"permission\">none</property>" << endl
        << "                <property name=\"rows\">" << object->fields.size()<< "</property>" << endl
        << "                <property name=\"vgap\">0</property>" << endl;

    for (Field::sequence::const_iterator field_it = object->fields.begin();
        field_it != object->fields.end();
        field_it++)
    {
        if (((*field_it)->name!="id") && ((*field_it)->name!="type"))
        {
            generateFieldUI(*field_it,os,indent);
        }
    }

    os  << "           </object>" << endl
        << "        </object>" << endl;

    return true;
}

bool wxFormBuilderGenerator::generate(const xml::ObjectPtr& object,ostream& os,size_t indent)
{
    generateDetailPanel(object,os,indent);
//    generateListPanel(object,os,indent);

    return true;
}

bool wxFormBuilderGenerator::generate(const Relation::Ptr &  relation,ostream& os,size_t indent)
{
    return true;
}

bool wxFormBuilderGenerator::generateCode(const ObjectModel* model)
{
    bool success;
    string ofname =   m_outputFilename.empty()
        ?  model->db->name +".fbp"
        :  m_outputFilename;

    ofstream ofs(getOutputFilename(ofname).c_str());

    ofs << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>" << endl
        << "<wxFormBuilder_Project>" << endl
        << "    <FileVersion major=\"1\" minor=\"10\" />" << endl
        << "    <object class=\"Project\" expanded=\"1\">" << endl
        << "        <property name=\"class_decoration\" />" << endl
        << "        <property name=\"code_generation\">C++</property>" << endl
        << "        <property name=\"disconnect_events\">1</property>" << endl
        << "        <property name=\"encoding\">UTF-8</property>" << endl
        << "        <property name=\"event_generation\">connect</property>" << endl
        << "        <property name=\"file\">ui</property>" << endl
        << "        <property name=\"first_id\">1000</property>" << endl
        << "        <property name=\"help_provider\">wxHelpControllerHelpProvider</property>" << endl
        << "        <property name=\"internationalize\">1</property>" << endl
        << "        <property name=\"name\">Litesql</property>" << endl
        << "        <property name=\"namespace\">"ui"</property>" << endl
        << "        <property name=\"path\">../</property>" << endl
        << "        <property name=\"precompiled_header\" />" << endl
        << "        <property name=\"relative_path\">1</property>" << endl
        << "        <property name=\"use_enum\">1</property>" << endl
        << "        <property name=\"use_microsoft_bom\">0</property>" << endl;

    success = CodeGenerator::generate(model->objects,ofs,2);
    success &= CodeGenerator::generate(model->relations,ofs,2);

    ofs << "    </object>" << endl
        << "</wxFormBuilder_Project>" << endl;
    ofs.close();
    return success;
}

<|endoftext|>


<commit_before>/**
 * Non-metric Space Library
 *
 * Main developers: Bilegsaikhan Naidan, Leonid Boytsov, Yury Malkov, Ben Frederickson, David Novak
 *
 * For the complete list of contributors and further details see:
 * https://github.com/nmslib/nmslib
 *
 * Copyright (c) 2013-2018
 *
 * This code is released under the
 * Apache License Version 2.0 http://www.apache.org/licenses/.
 *
 */
#if !defined(_MSC_VER) && !defined(__APPLE__)

#include <sys/time.h>

#include "logging.h"
#include "ztimer.h"
#include "bunit.h"

namespace similarity {

const unsigned TIMER_ERR_TOL = 200;

/*
 * These test is intended to run only on Unix-like systems.
 */

/**
 *  author: Preston Bannister
 */
class WallClockTimerBannister {
public:
    struct timeval t1, t2;
    WallClockTimerBannister() :
        t1(), t2() {
        gettimeofday(&t1, 0);
        t2 = t1;
    }
    void reset() {
        gettimeofday(&t1, 0);
        t2 = t1;
    }
    uint64_t elapsed() {
        return ((t2.tv_sec - t1.tv_sec) * 1000ULL * 1000ULL) + ((t2.tv_usec - t1. tv_usec));
    }
    uint64_t split() {
        gettimeofday(&t2, 0);
        return elapsed();
    }
};

void BurnCPU(size_t qty = 10000000000) {
  size_t sum = 0;
  for (size_t i = 0; i < qty; ++i) {
    sum += i;
    sum *= qty;
  }
  LOG(LIB_INFO) << "Ignore: " << sum;
}

#ifdef DISABLE_LONG_TESTS
TEST(DISABLE_TestTimer) {
#else
TEST(TestTimer) {
#endif
  WallClockTimerBannister oldz;
  WallClockTimer          z;

  BurnCPU();
  oldz.split();
  z.split();

  LOG(LIB_INFO) << "Timer: " << z.elapsed() << " : " << oldz.elapsed();
  // We expect both timers to differ in at most 0.1 ms
  EXPECT_EQ(std::abs(static_cast<int64_t>(z.elapsed()) - static_cast<int64_t>(oldz.elapsed())) < TIMER_ERR_TOL, true);

  BurnCPU();
  oldz.split();
  z.split();

  LOG(LIB_INFO) << "Timer: " << z.elapsed() << " : " << oldz.elapsed();
  // We expect both timers to differ in at most 0.1 ms
  EXPECT_EQ(std::abs(static_cast<int64_t>(z.elapsed()) - static_cast<int64_t>(oldz.elapsed())) < TIMER_ERR_TOL, true);

  z.reset();
  oldz.reset();

  BurnCPU();
  oldz.split();
  z.split();

  LOG(LIB_INFO) << "Timer: " << z.elapsed() << " : " << oldz.elapsed();
  // We expect both timers to differ in at most 0.1 ms
  EXPECT_EQ(std::abs(static_cast<int64_t>(z.elapsed()) - static_cast<int64_t>(oldz.elapsed())) < TIMER_ERR_TOL, true);
}

}  // namespace similarity
#endif

<commit_msg>increasing timer diff tolerance.<commit_after>/**
 * Non-metric Space Library
 *
 * Main developers: Bilegsaikhan Naidan, Leonid Boytsov, Yury Malkov, Ben Frederickson, David Novak
 *
 * For the complete list of contributors and further details see:
 * https://github.com/nmslib/nmslib
 *
 * Copyright (c) 2013-2018
 *
 * This code is released under the
 * Apache License Version 2.0 http://www.apache.org/licenses/.
 *
 */
#if !defined(_MSC_VER) && !defined(__APPLE__)

#include <sys/time.h>

#include "logging.h"
#include "ztimer.h"
#include "bunit.h"

namespace similarity {

// We expect both timers to differ in at most 1 ms
const unsigned TIMER_ERR_TOL = 1000;

/*
 * These test is intended to run only on Unix-like systems.
 */

/**
 *  author: Preston Bannister
 */
class WallClockTimerBannister {
public:
    struct timeval t1, t2;
    WallClockTimerBannister() :
        t1(), t2() {
        gettimeofday(&t1, 0);
        t2 = t1;
    }
    void reset() {
        gettimeofday(&t1, 0);
        t2 = t1;
    }
    uint64_t elapsed() {
        return ((t2.tv_sec - t1.tv_sec) * 1000ULL * 1000ULL) + ((t2.tv_usec - t1. tv_usec));
    }
    uint64_t split() {
        gettimeofday(&t2, 0);
        return elapsed();
    }
};

void BurnCPU(size_t qty = 10000000000) {
  size_t sum = 0;
  for (size_t i = 0; i < qty; ++i) {
    sum += i;
    sum *= qty;
  }
  LOG(LIB_INFO) << "Ignore: " << sum;
}

#ifdef DISABLE_LONG_TESTS
TEST(DISABLE_TestTimer) {
#else
TEST(TestTimer) {
#endif
  WallClockTimerBannister oldz;
  WallClockTimer          z;

  BurnCPU();
  oldz.split();
  z.split();

  LOG(LIB_INFO) << "Timer: " << z.elapsed() << " : " << oldz.elapsed();
  EXPECT_EQ(std::abs(static_cast<int64_t>(z.elapsed()) - static_cast<int64_t>(oldz.elapsed())) < TIMER_ERR_TOL, true);

  BurnCPU();
  oldz.split();
  z.split();

  LOG(LIB_INFO) << "Timer: " << z.elapsed() << " : " << oldz.elapsed();
  EXPECT_EQ(std::abs(static_cast<int64_t>(z.elapsed()) - static_cast<int64_t>(oldz.elapsed())) < TIMER_ERR_TOL, true);

  z.reset();
  oldz.reset();

  BurnCPU();
  oldz.split();
  z.split();

  LOG(LIB_INFO) << "Timer: " << z.elapsed() << " : " << oldz.elapsed();
  EXPECT_EQ(std::abs(static_cast<int64_t>(z.elapsed()) - static_cast<int64_t>(oldz.elapsed())) < TIMER_ERR_TOL, true);
}

}  // namespace similarity
#endif

<|endoftext|>


<commit_before>#include <iostream>

#include "SDL_image.h"

int main() {
    return 0;
}
<commit_msg>included glyph extraction header<commit_after>#include <iostream>

#include "grayscale_bitmap.h"
#include "glyph_extractor.h"

int main() {
    return 0;
}
<|endoftext|>


<commit_before>#include <iostream>

#include "grayscale_bitmap.h"
#include "freetype_interface.h"

int main() {
    return 0;
}
<commit_msg>included sdl_interface header to main module<commit_after>#include <iostream>

#include "grayscale_bitmap.h"
#include "freetype_interface.h"
#include "sdl_interface.h"

int main() {
    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 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 "content/browser/browser_child_process_host.h"

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "content/browser/browser_thread.h"
#include "content/browser/content_browser_client.h"
#include "content/browser/renderer_host/resource_message_filter.h"
#include "content/browser/trace_message_filter.h"
#include "content/common/content_switches.h"
#include "content/common/notification_service.h"
#include "content/common/plugin_messages.h"
#include "content/common/process_watcher.h"
#include "content/common/result_codes.h"

namespace {

typedef std::list<BrowserChildProcessHost*> ChildProcessList;
static base::LazyInstance<ChildProcessList> g_child_process_list(
    base::LINKER_INITIALIZED);

// The NotificationTask is used to notify about plugin process connection/
// disconnection. It is needed because the notifications in the
// NotificationService must happen in the main thread.
class ChildNotificationTask : public Task {
 public:
  ChildNotificationTask(
      int notification_type, ChildProcessInfo* info)
      : notification_type_(notification_type), info_(*info) { }

  virtual void Run() {
    NotificationService::current()->
        Notify(notification_type_, NotificationService::AllSources(),
               Details<ChildProcessInfo>(&info_));
  }

 private:
  int notification_type_;
  ChildProcessInfo info_;
};

}  // namespace

BrowserChildProcessHost::BrowserChildProcessHost(
    ChildProcessInfo::ProcessType type)
    : ChildProcessInfo(type, -1),
      ALLOW_THIS_IN_INITIALIZER_LIST(client_(this)) {
  AddFilter(new TraceMessageFilter);

  g_child_process_list.Get().push_back(this);
}

BrowserChildProcessHost::~BrowserChildProcessHost() {
  g_child_process_list.Get().remove(this);
}

// static
void BrowserChildProcessHost::TerminateAll() {
  // Make a copy since the ChildProcessHost dtor mutates the original list.
  ChildProcessList copy = g_child_process_list.Get();
  STLDeleteElements(&copy);
}

void BrowserChildProcessHost::Launch(
#if defined(OS_WIN)
    const FilePath& exposed_dir,
#elif defined(OS_POSIX)
    bool use_zygote,
    const base::environment_vector& environ,
#endif
    CommandLine* cmd_line) {

  content::GetContentClient()->browser()->AppendExtraCommandLineSwitches(
      cmd_line, id());

  child_process_.reset(new ChildProcessLauncher(
#if defined(OS_WIN)
      exposed_dir,
#elif defined(OS_POSIX)
      use_zygote,
      environ,
      channel()->GetClientFileDescriptor(),
#endif
      cmd_line,
      &client_));
}

base::ProcessHandle BrowserChildProcessHost::GetChildProcessHandle() const {
  DCHECK(child_process_.get())
      << "Requesting a child process handle before launching.";
  DCHECK(child_process_->GetHandle())
      << "Requesting a child process handle before launch has completed OK.";
  return child_process_->GetHandle();
}

void BrowserChildProcessHost::ForceShutdown() {
  g_child_process_list.Get().remove(this);
  ChildProcessHost::ForceShutdown();
}

void BrowserChildProcessHost::SetTerminateChildOnShutdown(
  bool terminate_on_shutdown) {
  child_process_->SetTerminateChildOnShutdown(terminate_on_shutdown);
}

void BrowserChildProcessHost::Notify(int type) {
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE, new ChildNotificationTask(type, this));
}

base::TerminationStatus BrowserChildProcessHost::GetChildTerminationStatus(
    int* exit_code) {
  return child_process_->GetChildTerminationStatus(exit_code);
}

void BrowserChildProcessHost::OnChildDied() {
  if (handle() != base::kNullProcessHandle) {
    int exit_code;
    base::TerminationStatus status = GetChildTerminationStatus(&exit_code);
    switch (status) {
      case base::TERMINATION_STATUS_PROCESS_CRASHED:
      case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: {
        OnProcessCrashed(exit_code);

        // Report that this child process crashed.
        Notify(content::NOTIFICATION_CHILD_PROCESS_CRASHED);
        UMA_HISTOGRAM_COUNTS("ChildProcess.Crashes", this->type());
        break;
      }
      case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: {
        OnProcessWasKilled(exit_code);

        // Report that this child process was killed.
        Notify(content::NOTIFICATION_CHILD_PROCESS_WAS_KILLED);
        UMA_HISTOGRAM_COUNTS("ChildProcess.Kills", this->type());
        break;
      }
      default:
        break;
    }
    // Notify in the main loop of the disconnection.
    Notify(content::NOTIFICATION_CHILD_PROCESS_HOST_DISCONNECTED);
  }
  ChildProcessHost::OnChildDied();
}

void BrowserChildProcessHost::ShutdownStarted() {
  // Must remove the process from the list now, in case it gets used for a
  // new instance before our watcher tells us that the process terminated.
  g_child_process_list.Get().remove(this);
}

BrowserChildProcessHost::ClientHook::ClientHook(BrowserChildProcessHost* host)
    : host_(host) {
}

void BrowserChildProcessHost::ClientHook::OnProcessLaunched() {
  if (!host_->child_process_->GetHandle()) {
    host_->OnChildDied();
    return;
  }
  host_->set_handle(host_->child_process_->GetHandle());
  host_->OnProcessLaunched();
}

BrowserChildProcessHost::Iterator::Iterator()
    : all_(true), type_(UNKNOWN_PROCESS) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) <<
          "ChildProcessInfo::Iterator must be used on the IO thread.";
  iterator_ = g_child_process_list.Get().begin();
}

BrowserChildProcessHost::Iterator::Iterator(ChildProcessInfo::ProcessType type)
    : all_(false), type_(type) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) <<
          "ChildProcessInfo::Iterator must be used on the IO thread.";
  iterator_ = g_child_process_list.Get().begin();
  if (!Done() && (*iterator_)->type() != type_)
    ++(*this);
}

BrowserChildProcessHost* BrowserChildProcessHost::Iterator::operator++() {
  do {
    ++iterator_;
    if (Done())
      break;

    if (!all_ && (*iterator_)->type() != type_)
      continue;

    return *iterator_;
  } while (true);

  return NULL;
}

bool BrowserChildProcessHost::Iterator::Done() {
  return iterator_ == g_child_process_list.Get().end();
}
<commit_msg>Keep cached handle better in sync with that in process launcher.<commit_after>// Copyright (c) 2011 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 "content/browser/browser_child_process_host.h"

#include "base/command_line.h"
#include "base/file_path.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "content/browser/browser_thread.h"
#include "content/browser/content_browser_client.h"
#include "content/browser/renderer_host/resource_message_filter.h"
#include "content/browser/trace_message_filter.h"
#include "content/common/content_switches.h"
#include "content/common/notification_service.h"
#include "content/common/plugin_messages.h"
#include "content/common/process_watcher.h"
#include "content/common/result_codes.h"

namespace {

typedef std::list<BrowserChildProcessHost*> ChildProcessList;
static base::LazyInstance<ChildProcessList> g_child_process_list(
    base::LINKER_INITIALIZED);

// The NotificationTask is used to notify about plugin process connection/
// disconnection. It is needed because the notifications in the
// NotificationService must happen in the main thread.
class ChildNotificationTask : public Task {
 public:
  ChildNotificationTask(
      int notification_type, ChildProcessInfo* info)
      : notification_type_(notification_type), info_(*info) { }

  virtual void Run() {
    NotificationService::current()->
        Notify(notification_type_, NotificationService::AllSources(),
               Details<ChildProcessInfo>(&info_));
  }

 private:
  int notification_type_;
  ChildProcessInfo info_;
};

}  // namespace

BrowserChildProcessHost::BrowserChildProcessHost(
    ChildProcessInfo::ProcessType type)
    : ChildProcessInfo(type, -1),
      ALLOW_THIS_IN_INITIALIZER_LIST(client_(this)) {
  AddFilter(new TraceMessageFilter);

  g_child_process_list.Get().push_back(this);
}

BrowserChildProcessHost::~BrowserChildProcessHost() {
  g_child_process_list.Get().remove(this);
}

// static
void BrowserChildProcessHost::TerminateAll() {
  // Make a copy since the ChildProcessHost dtor mutates the original list.
  ChildProcessList copy = g_child_process_list.Get();
  STLDeleteElements(&copy);
}

void BrowserChildProcessHost::Launch(
#if defined(OS_WIN)
    const FilePath& exposed_dir,
#elif defined(OS_POSIX)
    bool use_zygote,
    const base::environment_vector& environ,
#endif
    CommandLine* cmd_line) {

  content::GetContentClient()->browser()->AppendExtraCommandLineSwitches(
      cmd_line, id());

  child_process_.reset(new ChildProcessLauncher(
#if defined(OS_WIN)
      exposed_dir,
#elif defined(OS_POSIX)
      use_zygote,
      environ,
      channel()->GetClientFileDescriptor(),
#endif
      cmd_line,
      &client_));
}

base::ProcessHandle BrowserChildProcessHost::GetChildProcessHandle() const {
  DCHECK(child_process_.get())
      << "Requesting a child process handle before launching.";
  DCHECK(child_process_->GetHandle())
      << "Requesting a child process handle before launch has completed OK.";
  return child_process_->GetHandle();
}

void BrowserChildProcessHost::ForceShutdown() {
  g_child_process_list.Get().remove(this);
  ChildProcessHost::ForceShutdown();
}

void BrowserChildProcessHost::SetTerminateChildOnShutdown(
  bool terminate_on_shutdown) {
  child_process_->SetTerminateChildOnShutdown(terminate_on_shutdown);
}

void BrowserChildProcessHost::Notify(int type) {
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE, new ChildNotificationTask(type, this));
}

base::TerminationStatus BrowserChildProcessHost::GetChildTerminationStatus(
    int* exit_code) {
  return child_process_->GetChildTerminationStatus(exit_code);
}

void BrowserChildProcessHost::OnChildDied() {
  // This may be called by both the channel's OnChannelError handler
  // as well as the process launcher's OnProcessLaunched handler, so
  // we need to be careful about the state of the process launcher here.
  if (!child_process_->IsStarting())
    set_handle(child_process_->GetHandle());
  if (handle() != base::kNullProcessHandle) {
    int exit_code;
    base::TerminationStatus status = GetChildTerminationStatus(&exit_code);
    switch (status) {
      case base::TERMINATION_STATUS_PROCESS_CRASHED:
      case base::TERMINATION_STATUS_ABNORMAL_TERMINATION: {
        OnProcessCrashed(exit_code);

        // Report that this child process crashed.
        Notify(content::NOTIFICATION_CHILD_PROCESS_CRASHED);
        UMA_HISTOGRAM_COUNTS("ChildProcess.Crashes", this->type());
        break;
      }
      case base::TERMINATION_STATUS_PROCESS_WAS_KILLED: {
        OnProcessWasKilled(exit_code);

        // Report that this child process was killed.
        Notify(content::NOTIFICATION_CHILD_PROCESS_WAS_KILLED);
        UMA_HISTOGRAM_COUNTS("ChildProcess.Kills", this->type());
        break;
      }
      default:
        break;
    }
    // Notify in the main loop of the disconnection.
    Notify(content::NOTIFICATION_CHILD_PROCESS_HOST_DISCONNECTED);
  }
  ChildProcessHost::OnChildDied();
}

void BrowserChildProcessHost::ShutdownStarted() {
  // Must remove the process from the list now, in case it gets used for a
  // new instance before our watcher tells us that the process terminated.
  g_child_process_list.Get().remove(this);
}

BrowserChildProcessHost::ClientHook::ClientHook(BrowserChildProcessHost* host)
    : host_(host) {
}

void BrowserChildProcessHost::ClientHook::OnProcessLaunched() {
  if (!host_->child_process_->GetHandle()) {
    host_->OnChildDied();
    return;
  }
  host_->set_handle(host_->child_process_->GetHandle());
  host_->OnProcessLaunched();
}

BrowserChildProcessHost::Iterator::Iterator()
    : all_(true), type_(UNKNOWN_PROCESS) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) <<
          "ChildProcessInfo::Iterator must be used on the IO thread.";
  iterator_ = g_child_process_list.Get().begin();
}

BrowserChildProcessHost::Iterator::Iterator(ChildProcessInfo::ProcessType type)
    : all_(false), type_(type) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)) <<
          "ChildProcessInfo::Iterator must be used on the IO thread.";
  iterator_ = g_child_process_list.Get().begin();
  if (!Done() && (*iterator_)->type() != type_)
    ++(*this);
}

BrowserChildProcessHost* BrowserChildProcessHost::Iterator::operator++() {
  do {
    ++iterator_;
    if (Done())
      break;

    if (!all_ && (*iterator_)->type() != type_)
      continue;

    return *iterator_;
  } while (true);

  return NULL;
}

bool BrowserChildProcessHost::Iterator::Done() {
  return iterator_ == g_child_process_list.Get().end();
}
<|endoftext|>