<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * 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/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#include "RecentlyUsedMasterPages.hxx"
#include "MasterPageObserver.hxx"
#include "MasterPagesSelector.hxx"
#include "MasterPageDescriptor.hxx"
#include "tools/ConfigurationAccess.hxx"
#include "drawdoc.hxx"
#include "sdpage.hxx"

#include <algorithm>
#include <vector>

#include <comphelper/processfactory.hxx>
#include "unomodel.hxx"
#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
#include <com/sun/star/drawing/XDrawPages.hpp>
#include <com/sun/star/frame/XComponentLoader.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/PropertyState.hpp>
#include <unotools/confignode.hxx>
#include <osl/doublecheckedlocking.h>
#include <osl/getglobalmutex.hxx>

using namespace ::std;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

namespace {

static const OUString& GetPathToImpressConfigurationRoot (void)
{
    static const OUString sPathToImpressConfigurationRoot ("/org.openoffice.Office.Impress/");
    return sPathToImpressConfigurationRoot;
}
static const OUString& GetPathToSetNode (void)
{
    static const OUString sPathToSetNode("MultiPaneGUI/ToolPanel/RecentlyUsedMasterPages");
    return sPathToSetNode;
}

class Descriptor
{
public:
    OUString msURL;
    OUString msName;
    ::sd::sidebar::MasterPageContainer::Token maToken;
    Descriptor (const OUString& rsURL, const OUString& rsName)
        : msURL(rsURL),
          msName(rsName),
          maToken(::sd::sidebar::MasterPageContainer::NIL_TOKEN)
    {}
    Descriptor (::sd::sidebar::MasterPageContainer::Token aToken,
        const OUString& rsURL, const OUString& rsName)
        : msURL(rsURL),
          msName(rsName),
          maToken(aToken)
    {}
    class TokenComparator
    { public:
        TokenComparator(::sd::sidebar::MasterPageContainer::Token aToken)
            : maToken(aToken) {}
        bool operator () (const Descriptor& rDescriptor)
        { return maToken==rDescriptor.maToken; }
    private: ::sd::sidebar::MasterPageContainer::Token maToken;
    };
};

} // end of anonymous namespace

namespace sd { namespace sidebar {

class RecentlyUsedMasterPages::MasterPageList : public ::std::vector<Descriptor>
{
public:
    MasterPageList (void) {}
};

RecentlyUsedMasterPages* RecentlyUsedMasterPages::mpInstance = NULL;

RecentlyUsedMasterPages&  RecentlyUsedMasterPages::Instance (void)
{
    if (mpInstance == NULL)
    {
        ::osl::GetGlobalMutex aMutexFunctor;
        ::osl::MutexGuard aGuard (aMutexFunctor());
        if (mpInstance == NULL)
        {
            RecentlyUsedMasterPages* pInstance = new RecentlyUsedMasterPages();
            pInstance->LateInit();
            SdGlobalResourceContainer::Instance().AddResource (
                ::std::auto_ptr<SdGlobalResource>(pInstance));
            OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
            mpInstance = pInstance;
        }
    }
    else {
        OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
    }

    return *mpInstance;
}

RecentlyUsedMasterPages::RecentlyUsedMasterPages (void)
    : maListeners(),
      mpMasterPages(new MasterPageList()),
      mnMaxListSize(8),
      mpContainer(new MasterPageContainer())
{
}

RecentlyUsedMasterPages::~RecentlyUsedMasterPages (void)
{
    Link aLink (LINK(this,RecentlyUsedMasterPages,MasterPageContainerChangeListener));
    mpContainer->RemoveChangeListener(aLink);

    MasterPageObserver::Instance().RemoveEventListener(
        LINK(this,RecentlyUsedMasterPages,MasterPageChangeListener));
}

void RecentlyUsedMasterPages::LateInit (void)
{
    Link aLink (LINK(this,RecentlyUsedMasterPages,MasterPageContainerChangeListener));
    mpContainer->AddChangeListener(aLink);

    LoadPersistentValues ();
    MasterPageObserver::Instance().AddEventListener(
        LINK(this,RecentlyUsedMasterPages,MasterPageChangeListener));
}

void RecentlyUsedMasterPages::LoadPersistentValues (void)
{
    try
    {
        tools::ConfigurationAccess aConfiguration (
            GetPathToImpressConfigurationRoot(),
            tools::ConfigurationAccess::READ_ONLY);
        Reference<container::XNameAccess> xSet (
            aConfiguration.GetConfigurationNode(GetPathToSetNode()),
            UNO_QUERY);
        if ( ! xSet.is())
            return;

        const OUString sURLMemberName("URL");
        const OUString sNameMemberName("Name");
        OUString sURL;
        OUString sName;

        // Read the names and URLs of the master pages.
        Sequence<OUString> aKeys (xSet->getElementNames());
        mpMasterPages->clear();
        mpMasterPages->reserve(aKeys.getLength());
        for (int i=0; i<aKeys.getLength(); i++)
        {
            Reference<container::XNameAccess> xSetItem (
                xSet->getByName(aKeys[i]), UNO_QUERY);
            if (xSetItem.is())
            {
                Any aURL (xSetItem->getByName(sURLMemberName));
                Any aName (xSetItem->getByName(sNameMemberName));
                aURL >>= sURL;
                aName >>= sName;
                SharedMasterPageDescriptor pDescriptor (new MasterPageDescriptor(
                    MasterPageContainer::TEMPLATE,
                    -1,
                    sURL,
                    OUString(),
                    sName,
                    false,
                    ::boost::shared_ptr<PageObjectProvider>(
                        new TemplatePageObjectProvider(sURL)),
                    ::boost::shared_ptr<PreviewProvider>(
                        new TemplatePreviewProvider(sURL))));
                // For user supplied templates we use a different
                // preview provider: The preview in the document shows
                // not only shapes on the master page but also shapes on
                // the foreground.  This is misleading and therefore
                // these previews are discarded and created directly
                // from the page objects.
                if (pDescriptor->GetURLClassification() == MasterPageDescriptor::URLCLASS_USER)
                    pDescriptor->mpPreviewProvider = ::boost::shared_ptr<PreviewProvider>(
                        new PagePreviewProvider());
                MasterPageContainer::Token aToken (mpContainer->PutMasterPage(pDescriptor));
                mpMasterPages->push_back(Descriptor(aToken,sURL,sName));
            }
        }

        ResolveList();
    }
    catch (Exception&)
    {
        // Ignore exception.
    }
}

void RecentlyUsedMasterPages::SavePersistentValues (void)
{
    try
    {
        tools::ConfigurationAccess aConfiguration (
            GetPathToImpressConfigurationRoot(),
            tools::ConfigurationAccess::READ_WRITE);
        Reference<container::XNameContainer> xSet (
            aConfiguration.GetConfigurationNode(GetPathToSetNode()),
            UNO_QUERY);
        if ( ! xSet.is())
            return;

        // Clear the set.
        Sequence<OUString> aKeys (xSet->getElementNames());
        sal_Int32 i;
        for (i=0; i<aKeys.getLength(); i++)
            xSet->removeByName (aKeys[i]);

        // Fill it with the URLs of this object.
        const OUString sURLMemberName("URL");
        const OUString sNameMemberName("Name");
        Any aValue;
        Reference<lang::XSingleServiceFactory> xChildFactory (
            xSet, UNO_QUERY);
        if ( ! xChildFactory.is())
            return;
        MasterPageList::const_iterator iDescriptor;
        sal_Int32 nIndex(0);
        for (iDescriptor=mpMasterPages->begin();
                iDescriptor!=mpMasterPages->end();
                ++iDescriptor,++nIndex)
        {
            // Create new child.
            OUString sKey ("index_");
            sKey += OUString::number(nIndex);
            Reference<container::XNameReplace> xChild(
                xChildFactory->createInstance(), UNO_QUERY);
            if (xChild.is())
            {
                xSet->insertByName (sKey, makeAny(xChild));

                aValue <<= OUString(iDescriptor->msURL);
                xChild->replaceByName (sURLMemberName, aValue);

                aValue <<= OUString(iDescriptor->msName);
                xChild->replaceByName (sNameMemberName, aValue);
            }
        }

        // Write the data back to disk.
        aConfiguration.CommitChanges();
    }
    catch (Exception&)
    {
        // Ignore exception.
    }
}

void RecentlyUsedMasterPages::AddEventListener (const Link& rEventListener)
{
    if (::std::find (
        maListeners.begin(),
        maListeners.end(),
        rEventListener) == maListeners.end())
    {
        maListeners.push_back (rEventListener);
    }
}

void RecentlyUsedMasterPages::RemoveEventListener (const Link& rEventListener)
{
    maListeners.erase (
        ::std::find (
            maListeners.begin(),
            maListeners.end(),
            rEventListener));
}

int RecentlyUsedMasterPages::GetMasterPageCount (void) const
{
    return mpMasterPages->size();
}

MasterPageContainer::Token RecentlyUsedMasterPages::GetTokenForIndex (sal_uInt32 nIndex) const
{
    if(nIndex<mpMasterPages->size())
        return (*mpMasterPages)[nIndex].maToken;
    else
        return MasterPageContainer::NIL_TOKEN;
}

void RecentlyUsedMasterPages::SendEvent (void)
{
    ::std::vector<Link>::iterator aLink (maListeners.begin());
    ::std::vector<Link>::iterator aEnd (maListeners.end());
    while (aLink!=aEnd)
    {
        aLink->Call (NULL);
        ++aLink;
    }
}

IMPL_LINK(RecentlyUsedMasterPages, MasterPageChangeListener,
    MasterPageObserverEvent*, pEvent)
{
    switch (pEvent->meType)
    {
        case MasterPageObserverEvent::ET_MASTER_PAGE_ADDED:
        case MasterPageObserverEvent::ET_MASTER_PAGE_EXISTS:
            AddMasterPage(
                mpContainer->GetTokenForStyleName(pEvent->mrMasterPageName));
            break;

        case MasterPageObserverEvent::ET_MASTER_PAGE_REMOVED:
            // Do not change the list of recently master pages (the deleted
            // page was recently used) but tell the listeners.  They may want
            // to update their lists.
            SendEvent();
            break;
    }
    return 0;
}

IMPL_LINK(RecentlyUsedMasterPages, MasterPageContainerChangeListener,
    MasterPageContainerChangeEvent*, pEvent)
{
    if (pEvent != NULL)
        switch (pEvent->meEventType)
        {
            case MasterPageContainerChangeEvent::CHILD_ADDED:
            case MasterPageContainerChangeEvent::CHILD_REMOVED:
            case MasterPageContainerChangeEvent::INDEX_CHANGED:
            case MasterPageContainerChangeEvent::INDEXES_CHANGED:
                ResolveList();
                break;

            default:
                // Ignored.
                break;
        }
    return 0;
}

void RecentlyUsedMasterPages::AddMasterPage (
    MasterPageContainer::Token aToken,
    bool bMakePersistent)
{
    // For the page to be inserted the token has to be valid and the page
    // has to have a valid URL.  This excludes master pages that do not come
    // from template files.
    if (aToken != MasterPageContainer::NIL_TOKEN
        && !mpContainer->GetURLForToken(aToken).isEmpty())
    {

        MasterPageList::iterator aIterator (
            ::std::find_if(mpMasterPages->begin(),mpMasterPages->end(),
                Descriptor::TokenComparator(aToken)));
        if (aIterator != mpMasterPages->end())
        {
            // When an entry for the given token already exists then remove
            // it now and insert it later at the head of the list.
            mpMasterPages->erase (aIterator);
        }

        mpMasterPages->insert(mpMasterPages->begin(),
            Descriptor(
                aToken,
                mpContainer->GetURLForToken(aToken),
                mpContainer->GetStyleNameForToken(aToken)));

        // Shorten list to maximal size.
        while (mpMasterPages->size() > mnMaxListSize)
        {
            mpMasterPages->pop_back ();
        }

        if (bMakePersistent)
            SavePersistentValues ();
        SendEvent();
    }
}

void RecentlyUsedMasterPages::ResolveList (void)
{
    bool bNotify (false);

    MasterPageList::iterator iDescriptor;
    for (iDescriptor=mpMasterPages->begin(); iDescriptor!=mpMasterPages->end(); ++iDescriptor)
    {
        if (iDescriptor->maToken == MasterPageContainer::NIL_TOKEN)
        {
            MasterPageContainer::Token aToken (mpContainer->GetTokenForURL(iDescriptor->msURL));
            iDescriptor->maToken = aToken;
            if (aToken != MasterPageContainer::NIL_TOKEN)
                bNotify = true;
        }
        else
        {
            if ( ! mpContainer->HasToken(iDescriptor->maToken))
            {
                iDescriptor->maToken = MasterPageContainer::NIL_TOKEN;
                bNotify = true;
            }
        }
    }

    if (bNotify)
        SendEvent();
}

} } // end of namespace sd::sidebar

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>-Werror,-Wunused-member-function<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * 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/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you 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 .
 */

#include "RecentlyUsedMasterPages.hxx"
#include "MasterPageObserver.hxx"
#include "MasterPagesSelector.hxx"
#include "MasterPageDescriptor.hxx"
#include "tools/ConfigurationAccess.hxx"
#include "drawdoc.hxx"
#include "sdpage.hxx"

#include <algorithm>
#include <vector>

#include <comphelper/processfactory.hxx>
#include "unomodel.hxx"
#include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
#include <com/sun/star/drawing/XDrawPages.hpp>
#include <com/sun/star/frame/XComponentLoader.hpp>
#include <com/sun/star/container/XNameAccess.hpp>
#include <com/sun/star/container/XHierarchicalNameAccess.hpp>
#include <com/sun/star/lang/XMultiServiceFactory.hpp>
#include <com/sun/star/beans/PropertyValue.hpp>
#include <com/sun/star/beans/PropertyState.hpp>
#include <unotools/confignode.hxx>
#include <osl/doublecheckedlocking.h>
#include <osl/getglobalmutex.hxx>

using namespace ::std;
using namespace ::com::sun::star;
using namespace ::com::sun::star::uno;

namespace {

static const OUString& GetPathToImpressConfigurationRoot (void)
{
    static const OUString sPathToImpressConfigurationRoot ("/org.openoffice.Office.Impress/");
    return sPathToImpressConfigurationRoot;
}
static const OUString& GetPathToSetNode (void)
{
    static const OUString sPathToSetNode("MultiPaneGUI/ToolPanel/RecentlyUsedMasterPages");
    return sPathToSetNode;
}

class Descriptor
{
public:
    OUString msURL;
    OUString msName;
    ::sd::sidebar::MasterPageContainer::Token maToken;
    Descriptor (::sd::sidebar::MasterPageContainer::Token aToken,
        const OUString& rsURL, const OUString& rsName)
        : msURL(rsURL),
          msName(rsName),
          maToken(aToken)
    {}
    class TokenComparator
    { public:
        TokenComparator(::sd::sidebar::MasterPageContainer::Token aToken)
            : maToken(aToken) {}
        bool operator () (const Descriptor& rDescriptor)
        { return maToken==rDescriptor.maToken; }
    private: ::sd::sidebar::MasterPageContainer::Token maToken;
    };
};

} // end of anonymous namespace

namespace sd { namespace sidebar {

class RecentlyUsedMasterPages::MasterPageList : public ::std::vector<Descriptor>
{
public:
    MasterPageList (void) {}
};

RecentlyUsedMasterPages* RecentlyUsedMasterPages::mpInstance = NULL;

RecentlyUsedMasterPages&  RecentlyUsedMasterPages::Instance (void)
{
    if (mpInstance == NULL)
    {
        ::osl::GetGlobalMutex aMutexFunctor;
        ::osl::MutexGuard aGuard (aMutexFunctor());
        if (mpInstance == NULL)
        {
            RecentlyUsedMasterPages* pInstance = new RecentlyUsedMasterPages();
            pInstance->LateInit();
            SdGlobalResourceContainer::Instance().AddResource (
                ::std::auto_ptr<SdGlobalResource>(pInstance));
            OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
            mpInstance = pInstance;
        }
    }
    else {
        OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
    }

    return *mpInstance;
}

RecentlyUsedMasterPages::RecentlyUsedMasterPages (void)
    : maListeners(),
      mpMasterPages(new MasterPageList()),
      mnMaxListSize(8),
      mpContainer(new MasterPageContainer())
{
}

RecentlyUsedMasterPages::~RecentlyUsedMasterPages (void)
{
    Link aLink (LINK(this,RecentlyUsedMasterPages,MasterPageContainerChangeListener));
    mpContainer->RemoveChangeListener(aLink);

    MasterPageObserver::Instance().RemoveEventListener(
        LINK(this,RecentlyUsedMasterPages,MasterPageChangeListener));
}

void RecentlyUsedMasterPages::LateInit (void)
{
    Link aLink (LINK(this,RecentlyUsedMasterPages,MasterPageContainerChangeListener));
    mpContainer->AddChangeListener(aLink);

    LoadPersistentValues ();
    MasterPageObserver::Instance().AddEventListener(
        LINK(this,RecentlyUsedMasterPages,MasterPageChangeListener));
}

void RecentlyUsedMasterPages::LoadPersistentValues (void)
{
    try
    {
        tools::ConfigurationAccess aConfiguration (
            GetPathToImpressConfigurationRoot(),
            tools::ConfigurationAccess::READ_ONLY);
        Reference<container::XNameAccess> xSet (
            aConfiguration.GetConfigurationNode(GetPathToSetNode()),
            UNO_QUERY);
        if ( ! xSet.is())
            return;

        const OUString sURLMemberName("URL");
        const OUString sNameMemberName("Name");
        OUString sURL;
        OUString sName;

        // Read the names and URLs of the master pages.
        Sequence<OUString> aKeys (xSet->getElementNames());
        mpMasterPages->clear();
        mpMasterPages->reserve(aKeys.getLength());
        for (int i=0; i<aKeys.getLength(); i++)
        {
            Reference<container::XNameAccess> xSetItem (
                xSet->getByName(aKeys[i]), UNO_QUERY);
            if (xSetItem.is())
            {
                Any aURL (xSetItem->getByName(sURLMemberName));
                Any aName (xSetItem->getByName(sNameMemberName));
                aURL >>= sURL;
                aName >>= sName;
                SharedMasterPageDescriptor pDescriptor (new MasterPageDescriptor(
                    MasterPageContainer::TEMPLATE,
                    -1,
                    sURL,
                    OUString(),
                    sName,
                    false,
                    ::boost::shared_ptr<PageObjectProvider>(
                        new TemplatePageObjectProvider(sURL)),
                    ::boost::shared_ptr<PreviewProvider>(
                        new TemplatePreviewProvider(sURL))));
                // For user supplied templates we use a different
                // preview provider: The preview in the document shows
                // not only shapes on the master page but also shapes on
                // the foreground.  This is misleading and therefore
                // these previews are discarded and created directly
                // from the page objects.
                if (pDescriptor->GetURLClassification() == MasterPageDescriptor::URLCLASS_USER)
                    pDescriptor->mpPreviewProvider = ::boost::shared_ptr<PreviewProvider>(
                        new PagePreviewProvider());
                MasterPageContainer::Token aToken (mpContainer->PutMasterPage(pDescriptor));
                mpMasterPages->push_back(Descriptor(aToken,sURL,sName));
            }
        }

        ResolveList();
    }
    catch (Exception&)
    {
        // Ignore exception.
    }
}

void RecentlyUsedMasterPages::SavePersistentValues (void)
{
    try
    {
        tools::ConfigurationAccess aConfiguration (
            GetPathToImpressConfigurationRoot(),
            tools::ConfigurationAccess::READ_WRITE);
        Reference<container::XNameContainer> xSet (
            aConfiguration.GetConfigurationNode(GetPathToSetNode()),
            UNO_QUERY);
        if ( ! xSet.is())
            return;

        // Clear the set.
        Sequence<OUString> aKeys (xSet->getElementNames());
        sal_Int32 i;
        for (i=0; i<aKeys.getLength(); i++)
            xSet->removeByName (aKeys[i]);

        // Fill it with the URLs of this object.
        const OUString sURLMemberName("URL");
        const OUString sNameMemberName("Name");
        Any aValue;
        Reference<lang::XSingleServiceFactory> xChildFactory (
            xSet, UNO_QUERY);
        if ( ! xChildFactory.is())
            return;
        MasterPageList::const_iterator iDescriptor;
        sal_Int32 nIndex(0);
        for (iDescriptor=mpMasterPages->begin();
                iDescriptor!=mpMasterPages->end();
                ++iDescriptor,++nIndex)
        {
            // Create new child.
            OUString sKey ("index_");
            sKey += OUString::number(nIndex);
            Reference<container::XNameReplace> xChild(
                xChildFactory->createInstance(), UNO_QUERY);
            if (xChild.is())
            {
                xSet->insertByName (sKey, makeAny(xChild));

                aValue <<= OUString(iDescriptor->msURL);
                xChild->replaceByName (sURLMemberName, aValue);

                aValue <<= OUString(iDescriptor->msName);
                xChild->replaceByName (sNameMemberName, aValue);
            }
        }

        // Write the data back to disk.
        aConfiguration.CommitChanges();
    }
    catch (Exception&)
    {
        // Ignore exception.
    }
}

void RecentlyUsedMasterPages::AddEventListener (const Link& rEventListener)
{
    if (::std::find (
        maListeners.begin(),
        maListeners.end(),
        rEventListener) == maListeners.end())
    {
        maListeners.push_back (rEventListener);
    }
}

void RecentlyUsedMasterPages::RemoveEventListener (const Link& rEventListener)
{
    maListeners.erase (
        ::std::find (
            maListeners.begin(),
            maListeners.end(),
            rEventListener));
}

int RecentlyUsedMasterPages::GetMasterPageCount (void) const
{
    return mpMasterPages->size();
}

MasterPageContainer::Token RecentlyUsedMasterPages::GetTokenForIndex (sal_uInt32 nIndex) const
{
    if(nIndex<mpMasterPages->size())
        return (*mpMasterPages)[nIndex].maToken;
    else
        return MasterPageContainer::NIL_TOKEN;
}

void RecentlyUsedMasterPages::SendEvent (void)
{
    ::std::vector<Link>::iterator aLink (maListeners.begin());
    ::std::vector<Link>::iterator aEnd (maListeners.end());
    while (aLink!=aEnd)
    {
        aLink->Call (NULL);
        ++aLink;
    }
}

IMPL_LINK(RecentlyUsedMasterPages, MasterPageChangeListener,
    MasterPageObserverEvent*, pEvent)
{
    switch (pEvent->meType)
    {
        case MasterPageObserverEvent::ET_MASTER_PAGE_ADDED:
        case MasterPageObserverEvent::ET_MASTER_PAGE_EXISTS:
            AddMasterPage(
                mpContainer->GetTokenForStyleName(pEvent->mrMasterPageName));
            break;

        case MasterPageObserverEvent::ET_MASTER_PAGE_REMOVED:
            // Do not change the list of recently master pages (the deleted
            // page was recently used) but tell the listeners.  They may want
            // to update their lists.
            SendEvent();
            break;
    }
    return 0;
}

IMPL_LINK(RecentlyUsedMasterPages, MasterPageContainerChangeListener,
    MasterPageContainerChangeEvent*, pEvent)
{
    if (pEvent != NULL)
        switch (pEvent->meEventType)
        {
            case MasterPageContainerChangeEvent::CHILD_ADDED:
            case MasterPageContainerChangeEvent::CHILD_REMOVED:
            case MasterPageContainerChangeEvent::INDEX_CHANGED:
            case MasterPageContainerChangeEvent::INDEXES_CHANGED:
                ResolveList();
                break;

            default:
                // Ignored.
                break;
        }
    return 0;
}

void RecentlyUsedMasterPages::AddMasterPage (
    MasterPageContainer::Token aToken,
    bool bMakePersistent)
{
    // For the page to be inserted the token has to be valid and the page
    // has to have a valid URL.  This excludes master pages that do not come
    // from template files.
    if (aToken != MasterPageContainer::NIL_TOKEN
        && !mpContainer->GetURLForToken(aToken).isEmpty())
    {

        MasterPageList::iterator aIterator (
            ::std::find_if(mpMasterPages->begin(),mpMasterPages->end(),
                Descriptor::TokenComparator(aToken)));
        if (aIterator != mpMasterPages->end())
        {
            // When an entry for the given token already exists then remove
            // it now and insert it later at the head of the list.
            mpMasterPages->erase (aIterator);
        }

        mpMasterPages->insert(mpMasterPages->begin(),
            Descriptor(
                aToken,
                mpContainer->GetURLForToken(aToken),
                mpContainer->GetStyleNameForToken(aToken)));

        // Shorten list to maximal size.
        while (mpMasterPages->size() > mnMaxListSize)
        {
            mpMasterPages->pop_back ();
        }

        if (bMakePersistent)
            SavePersistentValues ();
        SendEvent();
    }
}

void RecentlyUsedMasterPages::ResolveList (void)
{
    bool bNotify (false);

    MasterPageList::iterator iDescriptor;
    for (iDescriptor=mpMasterPages->begin(); iDescriptor!=mpMasterPages->end(); ++iDescriptor)
    {
        if (iDescriptor->maToken == MasterPageContainer::NIL_TOKEN)
        {
            MasterPageContainer::Token aToken (mpContainer->GetTokenForURL(iDescriptor->msURL));
            iDescriptor->maToken = aToken;
            if (aToken != MasterPageContainer::NIL_TOKEN)
                bNotify = true;
        }
        else
        {
            if ( ! mpContainer->HasToken(iDescriptor->maToken))
            {
                iDescriptor->maToken = MasterPageContainer::NIL_TOKEN;
                bNotify = true;
            }
        }
    }

    if (bNotify)
        SendEvent();
}

} } // end of namespace sd::sidebar

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>
#ifndef WIN32

# include <iostream>
# include <string>
# include <cstring>
# include <algorithm>
# include <stdexcept>

# include <unistd.h>
# include <sys/select.h>
# include <sys/types.h>
# include <sys/wait.h>
# include <sys/time.h>
# include <cstdio>
# include <errno.h>
# include <fcntl.h>
# include <stdio.h>

# include "api/IRequest.hpp"
# include "api/IBuffer.hpp"
# include "api/IBufferManager.hpp"
# include "api/constants.hpp"

# include "server/utils/Logger.hpp"
# include "Environment.hpp"
# include "Process.hpp"
# include "Utils.hpp"

# define READ_END   0
# define WRITE_END  1

UnixProcess::UnixProcess()
{
    this->_read_pipe[0] = -1;
    this->_read_pipe[1] = -1;
    this->_write_pipe[0] = -1;
    this->_write_pipe[1] = -1;
    this->_status = PROCESS_STATUS::STARTED;
    this->_wait = true;
}

UnixProcess::~UnixProcess()
{
    ::close(this->_write_pipe[1]);
    ::close(this->_read_pipe[0]);
}

char* const* UnixProcess::_getArguments()
{
    std::list<std::string>::const_iterator  it;
    std::list<std::string>::const_iterator  ite;
    char**                                  c_argv;
    std::string                             temp;
    zhttpd::api::uint32_t                      i;

    i = 0;
    it = this->_arguments->begin();
    ite = this->_arguments->end();
    c_argv = new char*[this->_arguments->size() + 1];
    for (; it != ite; it++)
    {
        c_argv[i] = new char[it->size() + 1];
        ::strncpy(c_argv[i], it->c_str(), it->size());
        c_argv[i][it->size()] = NULL;
        i++;
    }
    c_argv[i] = NULL;

    return (c_argv);
}

void UnixProcess::_execute()
{
    const char*       executable;
    char* const*      args;
    char* const*      env;

    executable = this->_executable->c_str();
    args = this->_getArguments();
    env = const_cast<char* const*>(this->_environment->getEnvironmentArray());
    ::execve(executable, args, env);
    // never reached !
    this->_status = PROCESS_STATUS::STARTED;
    _exit(EXIT_FAILURE);
}

bool UnixProcess::create(std::string const& executable,
                         std::list<std::string> const& arguments,
                         Environment const& environment,
                         char const* root_directory)
{
    if (::pipe(this->_read_pipe) < 0)
        throw std::runtime_error("pipe() failed: " + std::string(::strerror(errno)));
    if (::pipe(this->_write_pipe) < 0)
        throw std::runtime_error("pipe() failed: " + std::string(::strerror(errno)));
    this->_executable = &executable;
    this->_arguments = &arguments;
    this->_environment = &environment;

    if ((this->_pid = ::fork()) < 0)
        throw std::runtime_error("fork() failed: " + std::string(::strerror(errno)));
    if (this->_pid == 0)
    {
        ::chdir(root_directory);
        _childProcessusHandler();
    }
    else
        _parentProcessusHandler();
    this->_status = PROCESS_STATUS::RUN; // parent et fils ???!!!

    return(true);
}

bool UnixProcess::_childProcessusHandler()
{
    ::close(STDIN_FILENO);
    ::close(this->_write_pipe[WRITE_END]);
    if (::dup2(this->_write_pipe[READ_END], STDIN_FILENO) < 0)
        throw std::runtime_error("Child CGI process dup2() failed: " + std::string(::strerror(errno)));
    //::setvbuf(stdin,(char*)NULL, _IOLBF, 0);

    ::close(STDOUT_FILENO);
    ::close(this->_read_pipe[READ_END]);
    if (::dup2(this->_read_pipe[WRITE_END], STDOUT_FILENO) < 0)
        throw std::runtime_error("Child CGI process: dup2() failed: " + std::string(::strerror(errno)));
    //::setvbuf(stdout,(char*)NULL, _IONBF, 0);

    this->_execute();

    return (false);
}

bool UnixProcess::_parentProcessusHandler()
{
    ::close(this->_write_pipe[READ_END]);
    ::close(this->_read_pipe[WRITE_END]);
    return (false);
}

zhttpd::api::size_t UnixProcess::write(char const* buffer, zhttpd::api::size_t size)
{
    fd_set write_fd_set;
    struct timeval time;
    int nwrite = 0;
    int fd = this->_write_pipe[WRITE_END];

    if (buffer != NULL)
    {
        FD_ZERO(&write_fd_set);
        FD_SET(fd, &write_fd_set);
        time.tv_sec = 0;
        time.tv_usec = 0;
        if (::select(fd + 1, NULL,  &write_fd_set, NULL, &time) < 0)
           throw std::runtime_error("CGI module: select() failed on child read fd: " + std::string(::strerror(errno)));
        if (FD_ISSET(fd, &write_fd_set))
        {
            FD_CLR(fd, &write_fd_set);
            nwrite = ::write(fd, buffer, size);
            if (nwrite == -1)
                throw std::runtime_error("CGI: write() failed: " + std::string(::strerror(errno)));
            return (nwrite);
        }
    }

    return (0);
}

zhttpd::api::size_t UnixProcess::read(char* buffer, zhttpd::api::size_t size)
{
    fd_set read_set;
    struct timeval time;
    int nread = 0;
    int fd = this->_read_pipe[READ_END];

    FD_ZERO(&read_set);
    FD_SET(fd, &read_set);
    time.tv_sec = 0;
    time.tv_usec = 0;
    if (this->_status != PROCESS_STATUS::FINISHED)
    {
        if (::select(fd + 1, &read_set, NULL, NULL, &time) < 0)
            throw std::runtime_error("CGI module: select() failed: " + std::string(::strerror(errno)));
    }
    if (this->_status == PROCESS_STATUS::FINISHED || FD_ISSET(this->_read_pipe[0], &read_set))
    {
        FD_CLR(fd, &read_set);
        nread = ::read(fd, buffer, size);
        if (nread == -1)
            throw std::runtime_error("CGI: read() failed: " + std::string(::strerror(errno)));
        return (nread);
    }
    else
        return (0);
}

PROCESS_STATUS::Type          UnixProcess::getStatus() const
{
    if (this->_status != PROCESS_STATUS::FINISHED)
    {
        int status;
        ::waitpid(this->_pid, &status, WNOHANG);
        if (WIFEXITED(status))
            this->_status = PROCESS_STATUS::FINISHED;
    }
    return (this->_status);
}

#endif  /* !WIN32 */
<commit_msg>Force kill of forked process if request ends early<commit_after>
#ifndef WIN32

# include <iostream>
# include <string>
# include <cstring>
# include <algorithm>
# include <stdexcept>

# include <unistd.h>
# include <sys/select.h>
# include <sys/types.h>
# include <sys/wait.h>
# include <sys/time.h>
# include <cstdio>
# include <errno.h>
# include <fcntl.h>
# include <stdio.h>
# include <signal.h>

# include "api/IRequest.hpp"
# include "api/IBuffer.hpp"
# include "api/IBufferManager.hpp"
# include "api/constants.hpp"

# include "server/utils/Logger.hpp"
# include "Environment.hpp"
# include "Process.hpp"
# include "Utils.hpp"

# define READ_END   0
# define WRITE_END  1

UnixProcess::UnixProcess()
{
    this->_read_pipe[0] = -1;
    this->_read_pipe[1] = -1;
    this->_write_pipe[0] = -1;
    this->_write_pipe[1] = -1;
    this->_status = PROCESS_STATUS::STARTED;
    this->_wait = true;
}

UnixProcess::~UnixProcess()
{
    ::close(this->_write_pipe[1]);
    ::close(this->_read_pipe[0]);
    if (this->_status != PROCESS_STATUS::STARTED)
    {
        LOG_WARN("killing process " + zhttpd::Logger::toString(this->_pid));
        kill(this->_pid, SIGKILL);
    }
}

char* const* UnixProcess::_getArguments()
{
    std::list<std::string>::const_iterator  it;
    std::list<std::string>::const_iterator  ite;
    char**                                  c_argv;
    std::string                             temp;
    zhttpd::api::uint32_t                      i;

    i = 0;
    it = this->_arguments->begin();
    ite = this->_arguments->end();
    c_argv = new char*[this->_arguments->size() + 1];
    for (; it != ite; it++)
    {
        c_argv[i] = new char[it->size() + 1];
        ::strncpy(c_argv[i], it->c_str(), it->size());
        c_argv[i][it->size()] = NULL;
        i++;
    }
    c_argv[i] = NULL;

    return (c_argv);
}

void UnixProcess::_execute()
{
    const char*       executable;
    char* const*      args;
    char* const*      env;

    executable = this->_executable->c_str();
    args = this->_getArguments();
    env = const_cast<char* const*>(this->_environment->getEnvironmentArray());
    ::execve(executable, args, env);
    // never reached !
    this->_status = PROCESS_STATUS::STARTED;
    _exit(EXIT_FAILURE);
}

bool UnixProcess::create(std::string const& executable,
                         std::list<std::string> const& arguments,
                         Environment const& environment,
                         char const* root_directory)
{
    if (::pipe(this->_read_pipe) < 0)
        throw std::runtime_error("pipe() failed: " + std::string(::strerror(errno)));
    if (::pipe(this->_write_pipe) < 0)
        throw std::runtime_error("pipe() failed: " + std::string(::strerror(errno)));
    this->_executable = &executable;
    this->_arguments = &arguments;
    this->_environment = &environment;

    if ((this->_pid = ::fork()) < 0)
        throw std::runtime_error("fork() failed: " + std::string(::strerror(errno)));
    if (this->_pid == 0)
    {
        ::chdir(root_directory);
        _childProcessusHandler();
    }
    else
        _parentProcessusHandler();
    this->_status = PROCESS_STATUS::RUN; // parent et fils ???!!!

    return(true);
}

bool UnixProcess::_childProcessusHandler()
{
    ::close(STDIN_FILENO);
    ::close(this->_write_pipe[WRITE_END]);
    if (::dup2(this->_write_pipe[READ_END], STDIN_FILENO) < 0)
        throw std::runtime_error("Child CGI process dup2() failed: " + std::string(::strerror(errno)));
    //::setvbuf(stdin,(char*)NULL, _IOLBF, 0);

    ::close(STDOUT_FILENO);
    ::close(this->_read_pipe[READ_END]);
    if (::dup2(this->_read_pipe[WRITE_END], STDOUT_FILENO) < 0)
        throw std::runtime_error("Child CGI process: dup2() failed: " + std::string(::strerror(errno)));
    //::setvbuf(stdout,(char*)NULL, _IONBF, 0);

    this->_execute();

    return (false);
}

bool UnixProcess::_parentProcessusHandler()
{
    ::close(this->_write_pipe[READ_END]);
    ::close(this->_read_pipe[WRITE_END]);
    return (false);
}

zhttpd::api::size_t UnixProcess::write(char const* buffer, zhttpd::api::size_t size)
{
    fd_set write_fd_set;
    struct timeval time;
    int nwrite = 0;
    int fd = this->_write_pipe[WRITE_END];

    if (buffer != NULL)
    {
        FD_ZERO(&write_fd_set);
        FD_SET(fd, &write_fd_set);
        time.tv_sec = 0;
        time.tv_usec = 0;
        if (::select(fd + 1, NULL,  &write_fd_set, NULL, &time) < 0)
           throw std::runtime_error("CGI module: select() failed on child read fd: " + std::string(::strerror(errno)));
        if (FD_ISSET(fd, &write_fd_set))
        {
            FD_CLR(fd, &write_fd_set);
            nwrite = ::write(fd, buffer, size);
            if (nwrite == -1)
                throw std::runtime_error("CGI: write() failed: " + std::string(::strerror(errno)));
            return (nwrite);
        }
    }

    return (0);
}

zhttpd::api::size_t UnixProcess::read(char* buffer, zhttpd::api::size_t size)
{
    fd_set read_set;
    struct timeval time;
    int nread = 0;
    int fd = this->_read_pipe[READ_END];

    FD_ZERO(&read_set);
    FD_SET(fd, &read_set);
    time.tv_sec = 0;
    time.tv_usec = 0;
    if (this->_status != PROCESS_STATUS::FINISHED)
    {
        if (::select(fd + 1, &read_set, NULL, NULL, &time) < 0)
            throw std::runtime_error("CGI module: select() failed: " + std::string(::strerror(errno)));
    }
    if (this->_status == PROCESS_STATUS::FINISHED || FD_ISSET(this->_read_pipe[0], &read_set))
    {
        FD_CLR(fd, &read_set);
        nread = ::read(fd, buffer, size);
        if (nread == -1)
            throw std::runtime_error("CGI: read() failed: " + std::string(::strerror(errno)));
        return (nread);
    }
    else
        return (0);
}

PROCESS_STATUS::Type          UnixProcess::getStatus() const
{
    if (this->_status != PROCESS_STATUS::FINISHED)
    {
        int status;
        ::waitpid(this->_pid, &status, WNOHANG);
        if (WIFEXITED(status))
            this->_status = PROCESS_STATUS::FINISHED;
    }
    return (this->_status);
}

#endif  /* !WIN32 */
<|endoftext|>


<commit_before>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                          License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __OPENCV_PRECOMP_H__
#define __OPENCV_PRECOMP_H__

#if _MSC_VER >= 1200
#pragma warning( disable: 4251 4710 4711 4514 4996 )
#endif

#ifdef HAVE_CONFIG_H
#include <cvconfig.h>
#endif

#include <iostream>
#include <limits>
#include <vector>
#include <algorithm>
#include <sstream>
#include <exception>

#include "opencv2/gpu/gpu.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#if defined(HAVE_CUDA)

    #include "internal_shared.hpp"
    #include "cuda_runtime_api.h"
    #include "cufft.h"
    #include "opencv2/gpu/stream_accessor.hpp"
    #include "npp.h"
    #include "npp_staging.h"
    #include "surf_key_point.h"

#define CUDART_MINIMUM_REQUIRED_VERSION 3020
#define NPP_MINIMUM_REQUIRED_VERSION 3216

#if (CUDART_VERSION < CUDART_MINIMUM_REQUIRED_VERSION)
    #error "Insufficient Cuda Runtime library version, please update it."
#endif

#if (NPP_VERSION_MAJOR*1000+NPP_VERSION_MINOR*100+NPP_VERSION_BUILD < NPP_MINIMUM_REQUIRED_VERSION)
    #error "Insufficient NPP version, please update it."
#endif

    static inline void throw_nogpu() { CV_Error(CV_GpuNotSupported, "The called functionality is disabled for current build or platform"); }

#else /* defined(HAVE_CUDA) */

    static inline void throw_nogpu() { CV_Error(CV_GpuNotSupported, "The library is compiled without GPU support"); }

#endif /* defined(HAVE_CUDA) */

#endif /* __OPENCV_PRECOMP_H__ */
<commit_msg>added missed include (for MSVC 2010)<commit_after>/*M///////////////////////////////////////////////////////////////////////////////////////
//
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
//  By downloading, copying, installing or using the software you agree to this license.
//  If you do not agree to this license, do not download, install,
//  copy or use the software.
//
//
//                          License Agreement
//                For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
//   * Redistribution's of source code must retain the above copyright notice,
//     this list of conditions and the following disclaimer.
//
//   * Redistribution's in binary form must reproduce the above copyright notice,
//     this list of conditions and the following disclaimer in the documentation
//     and/or other materials provided with the distribution.
//
//   * The name of the copyright holders may not be used to endorse or promote products
//     derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#ifndef __OPENCV_PRECOMP_H__
#define __OPENCV_PRECOMP_H__

#if _MSC_VER >= 1200
#pragma warning( disable: 4251 4710 4711 4514 4996 )
#endif

#ifdef HAVE_CONFIG_H
#include <cvconfig.h>
#endif

#include <iostream>
#include <limits>
#include <vector>
#include <algorithm>
#include <sstream>
#include <exception>
#include <iterator>

#include "opencv2/gpu/gpu.hpp"
#include "opencv2/imgproc/imgproc.hpp"

#if defined(HAVE_CUDA)

    #include "internal_shared.hpp"
    #include "cuda_runtime_api.h"
    #include "cufft.h"
    #include "opencv2/gpu/stream_accessor.hpp"
    #include "npp.h"
    #include "npp_staging.h"
    #include "surf_key_point.h"

#define CUDART_MINIMUM_REQUIRED_VERSION 3020
#define NPP_MINIMUM_REQUIRED_VERSION 3216

#if (CUDART_VERSION < CUDART_MINIMUM_REQUIRED_VERSION)
    #error "Insufficient Cuda Runtime library version, please update it."
#endif

#if (NPP_VERSION_MAJOR*1000+NPP_VERSION_MINOR*100+NPP_VERSION_BUILD < NPP_MINIMUM_REQUIRED_VERSION)
    #error "Insufficient NPP version, please update it."
#endif

    static inline void throw_nogpu() { CV_Error(CV_GpuNotSupported, "The called functionality is disabled for current build or platform"); }

#else /* defined(HAVE_CUDA) */

    static inline void throw_nogpu() { CV_Error(CV_GpuNotSupported, "The library is compiled without GPU support"); }

#endif /* defined(HAVE_CUDA) */

#endif /* __OPENCV_PRECOMP_H__ */
<|endoftext|>


<commit_before>//
//  GameEngine.cpp
//  yamiHikariGame
//
//  Created by slightair on 2013/07/28.
//
//

#include "GameEngine.h"
#include "SimpleAudioEngine.h"
#include "sha1.h"
#include "Constants.h"
#include "GameCenter.h"
#include "TitleScene.h"
#include "TutorialScene.h"
#include "GameScene.h"
#include "ResultScene.h"
#include "ItemListScene.h"
#include "Item.h"
#include "NotificationLayer.h"

#define kTransitionDuration 1.0
#define kGameTickInterval 0.1
#define kSurvivePoint 1
#define kStaminaConsumption 3
#define kWaitForResultDuration 3

#define kSavefileName "savedata.db"
#define kAchievementsFileName "achievements.plist"

static GameEngine *__sharedEngine = NULL;

GameEngine *GameEngine::sharedEngine()
{
    if (!__sharedEngine) {
        __sharedEngine = new GameEngine();
        __sharedEngine->init();
    }

    return __sharedEngine;
}

bool GameEngine::init()
{
    _achievements = CCArray::createWithContentsOfFile(kAchievementsFileName);
    _achievements->retain();

    return true;
}

void GameEngine::startTutorial(bool startGame)
{
    _startWithTutorial = startGame;
    CCTransitionFade *transition = CCTransitionFade::create(kTransitionDuration, TutorialScene::scene());
    CCDirector::sharedDirector()->replaceScene(transition);
}

void GameEngine::finishTutorial()
{
    if (_startWithTutorial) {
        startNewGame();
    }
    else {
        CCTransitionFade *transition = CCTransitionFade::create(kTransitionDuration, TitleScene::scene());
        CCDirector::sharedDirector()->replaceScene(transition);
    }
}

void GameEngine::startNewGame()
{
    _score = 0;
    _stamina = StaminaMax;
    _foundItems.clear();

    CCDirector *director = CCDirector::sharedDirector();
    CCTransitionFade *transition = CCTransitionFade::create(kTransitionDuration, GameScene::scene());
    director->replaceScene(transition);

    director->getScheduler()->scheduleSelector(schedule_selector(GameEngine::tick), this, kGameTickInterval, false);
}

void GameEngine::finishGame()
{
    CCDirector *director = CCDirector::sharedDirector();

    director->getScheduler()->unscheduleSelector(schedule_selector(GameEngine::tick), this);

    GameScene *gameScene = (GameScene *)director->getRunningScene()->getChildren()->objectAtIndex(0);
    gameScene->finishAnimations();

    CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect(SEGameOver);

    registerFoundItemCount();

    director->getScheduler()->scheduleSelector(schedule_selector(GameEngine::showResult), this, 0, 0, kWaitForResultDuration, false);

    registerActivities();
}

void GameEngine::tick()
{
    _stamina -= kStaminaConsumption;
    _score += kSurvivePoint;

    if (_stamina <= 0) {
        this->finishGame();
    }
}

void GameEngine::registerFoundItemCount()
{
    map<hiberlite::sqlid_t, int>::iterator iterator = _foundItems.begin();

    while (iterator != _foundItems.end()) {
        hiberlite::sqlid_t itemID = (*iterator).first;
        Item item = _items.at(itemID - 1);
        int count = (*iterator).second;

        item->updateCount(item->count + count);
        item.save();

        iterator++;
    }
}

void GameEngine::registerActivities()
{
    GameCenter *gameCenter = GameCenter::sharedCenter();

    CCUserDefault *userDefault = CCUserDefault::sharedUserDefault();
    int currentHighScore = userDefault->getIntegerForKey(HighScoreKey, 0);
    string currentHighScoreChecksum = userDefault->getStringForKey(HighScoreChecksumKey, "");

    if (currentHighScoreChecksum != generateScoreChecksum(currentHighScore)) {
        currentHighScore = 0;
    }

    int highScore = _score;
    if (_score > currentHighScore) {
        userDefault->setIntegerForKey(HighScoreKey, _score);
        userDefault->setStringForKey(HighScoreChecksumKey, generateScoreChecksum(_score));
        userDefault->flush();
    }
    else {
        highScore = currentHighScore;
    }
    gameCenter->registerHighScore(highScore);

    vector<Achievement> completedAchievements;

    Achievement firstPlayAchievement;
    firstPlayAchievement.setName(AchievementFirstPlayName);
    firstPlayAchievement.setIOSAchievementID(AchievementFirstPlayAchievementIDIOS);
    firstPlayAchievement.setProcess(1);
    firstPlayAchievement.setGoal(1);
    completedAchievements.push_back(firstPlayAchievement);

    CCObject *object = NULL;
    CCARRAY_FOREACH(_achievements, object) {
        CCDictionary *achievementInfo = (CCDictionary *)object;

        int count = ((CCString *)achievementInfo->objectForKey("count"))->intValue();
        CCArray *itemIDs = (CCArray *)achievementInfo->objectForKey("item_ids");

        int sum = 0;
        CCObject *itemID = NULL;
        CCARRAY_FOREACH(itemIDs, itemID) {
            int id = ((CCString *)itemID)->intValue();
            Item item = _items.at(id - 1);
            sum += item->count;
        }

        Achievement achievement;
        achievement.setName(((CCString *)achievementInfo->objectForKey("name"))->getCString());
        achievement.setIOSAchievementID(((CCString *)achievementInfo->objectForKey("ios_achievement_id"))->getCString());
        achievement.setProcess(sum);
        achievement.setGoal(count);
        completedAchievements.push_back(achievement);
    }

    gameCenter->registerAchievements(&completedAchievements);
}

void GameEngine::showResult()
{
    CCTransitionFade *transition = CCTransitionFade::create(kTransitionDuration, ResultScene::scene());
    CCDirector::sharedDirector()->replaceScene(transition);
}

void GameEngine::showItemList()
{
    CCTransitionFade *transition = CCTransitionFade::create(kTransitionDuration, ItemListScene::scene());
    CCDirector::sharedDirector()->replaceScene(transition);
}

void GameEngine::showRanking()
{
    GameCenter::sharedCenter()->showRanking();
}

void GameEngine::showTitle()
{
    CCTransitionFade *transition = CCTransitionFade::create(kTransitionDuration, TitleScene::scene());
    CCDirector::sharedDirector()->replaceScene(transition);
}

void GameEngine::confirmResetSaveData()
{
    NotificationLayer *confirmLayer = NotificationLayer::create();
    confirmLayer->setTitle(MessageConfirmResetSaveDataTitle);
    confirmLayer->setNoticeMessage(MessageConfirmResetSaveDataText);
    confirmLayer->setNotificationType(NOTIFICATION_LAYER_YES_NO);
    confirmLayer->setActionTarget(NOTIFICATION_LAYER_ACTION_NO, CCDirector::sharedDirector(), menu_selector(CCDirector::popScene));
    confirmLayer->setActionTarget(NOTIFICATION_LAYER_ACTION_YES, this, menu_selector(GameEngine::resetSaveData));

    CCScene *scene = CCScene::create();
    scene->addChild(confirmLayer);
    CCDirector::sharedDirector()->pushScene(scene);
}

void GameEngine::resetSaveData()
{
    rebuildSaveData();

    CCUserDefault *userDefault = CCUserDefault::sharedUserDefault();
    userDefault->setBoolForKey(TutorialStateKey, false);
    userDefault->flush();

    NotificationLayer *noticeLayer = NotificationLayer::create();
    noticeLayer->setTitle(MessageConfirmResetSaveDataTitle);
    noticeLayer->setNoticeMessage(MessageCompleteResetSaveDataText);
    noticeLayer->setNotificationType(NOTIFICATION_LAYER_OK_ONLY);
    noticeLayer->setActionTarget(NOTIFICATION_LAYER_ACTION_OK, CCDirector::sharedDirector(), menu_selector(CCDirector::popScene));

    CCScene *scene = CCScene::create();
    scene->addChild(noticeLayer);
    CCDirector::sharedDirector()->replaceScene(scene);
}

bool GameEngine::needsTutorial()
{
    CCUserDefault *userDefault = CCUserDefault::sharedUserDefault();
    bool tutorialDone = userDefault->getBoolForKey(TutorialStateKey, false);
    if (!tutorialDone) {
        userDefault->setBoolForKey(TutorialStateKey, true);
        userDefault->flush();
        return true;
    }
    return false;
}

int GameEngine::getScore()
{
    return _score;
}

int GameEngine::getStamina()
{
    return _stamina;
}

void GameEngine::addScore(int score)
{
    _score += score;
}

void GameEngine::addStamina(int stamina)
{
    if (_stamina + stamina > StaminaMax) {
        _stamina = StaminaMax;
    }
    else {
        _stamina += stamina;
    }
}

void GameEngine::loadSaveData()
{
    CCFileUtils *fileUtils = CCFileUtils::sharedFileUtils();
    bool forceRebuildSaveData = false;

    string saveFilePath = fileUtils->getWritablePath().append(kSavefileName);
    if (forceRebuildSaveData || !fileUtils->isFileExist(saveFilePath)) {
        copyInitialData(saveFilePath);
    }

    _db.open(saveFilePath);

    _items = _db.getAllBeans<_Item>();
    for (int i=0; i<_items.size(); i++) {
        if (!_items.at(i)->validate()) {
            CCLog("validation error!!");

            rebuildSaveData();

            NotificationLayer *noticeLayer = NotificationLayer::create();
            noticeLayer->setTitle(MessageInvalidDataTitle);
            noticeLayer->setNoticeMessage(MessageInvalidDataText);
            noticeLayer->setNotificationType(NOTIFICATION_LAYER_OK_ONLY);
            noticeLayer->setActionTarget(NOTIFICATION_LAYER_ACTION_OK, CCDirector::sharedDirector(), menu_selector(CCDirector::popScene));

            CCScene *scene = CCScene::create();
            scene->addChild(noticeLayer);
            CCDirector::sharedDirector()->pushScene(scene);

            return;
        }
    }
}

void GameEngine::rebuildSaveData()
{
    CCFileUtils *fileUtils = CCFileUtils::sharedFileUtils();

    _db.close();
    _items.clear();

    string saveFilePath = fileUtils->getWritablePath().append(kSavefileName);
    copyInitialData(saveFilePath);

    _db.open(saveFilePath);
    _items = _db.getAllBeans<_Item>();
}

void GameEngine::copyInitialData(string saveFilePath)
{
    CCFileUtils *fileUtils = CCFileUtils::sharedFileUtils();

    string initDBFilePath = fileUtils->fullPathForFilename("init.db");

    unsigned long nSize = 0;
    unsigned char* buffer = fileUtils->getFileData(initDBFilePath.c_str(), "rb", &nSize);

    if (buffer != NULL && nSize > 0) {
        FILE *dest = fopen(saveFilePath.c_str(), "wb");
        unsigned long result = fwrite(buffer, sizeof(char), nSize, dest);
        if (result < nSize) {
            CCLog("copy savedata failed. %ld", result);
        }
        fclose(dest);
    }
    CC_SAFE_DELETE_ARRAY(buffer);
}

void GameEngine::foundItem(hiberlite::sqlid_t itemID)
{
    Item item = _items.at(itemID - 1);

    addScore(item->score);
    addStamina(item->stamina);

    if (_foundItems.find(itemID) == _foundItems.end()) {
        _foundItems[itemID] = 1;
    }
    else {
        _foundItems[itemID] += 1;
    }
}

string GameEngine::generateScoreChecksum(int score)
{
    char input[64];
    unsigned char digest[SHA1DigestLength];
    char buf[ChecksumLength];

    sprintf(input, "%d:%s", score, ScoreChecksumSalt);

    SHA1 sha1;
    sha1.addBytes((unsigned char *)input, strlen(input));
    sha1.getDigest(digest, SHA1DigestLength);
    sprintf(buf, "%02x%02x%02x%02x", digest[0], digest[1], digest[2], digest[3]);

    return string(buf);
}

vector<Item> *GameEngine::getItems()
{
    return &_items;
}

map<hiberlite::sqlid_t, int> *GameEngine::getFoundItems()
{
    return &_foundItems;
}<commit_msg>ハイスコアのデータも初期化するようにした<commit_after>//
//  GameEngine.cpp
//  yamiHikariGame
//
//  Created by slightair on 2013/07/28.
//
//

#include "GameEngine.h"
#include "SimpleAudioEngine.h"
#include "sha1.h"
#include "Constants.h"
#include "GameCenter.h"
#include "TitleScene.h"
#include "TutorialScene.h"
#include "GameScene.h"
#include "ResultScene.h"
#include "ItemListScene.h"
#include "Item.h"
#include "NotificationLayer.h"

#define kTransitionDuration 1.0
#define kGameTickInterval 0.1
#define kSurvivePoint 1
#define kStaminaConsumption 3
#define kWaitForResultDuration 3

#define kSavefileName "savedata.db"
#define kAchievementsFileName "achievements.plist"

static GameEngine *__sharedEngine = NULL;

GameEngine *GameEngine::sharedEngine()
{
    if (!__sharedEngine) {
        __sharedEngine = new GameEngine();
        __sharedEngine->init();
    }

    return __sharedEngine;
}

bool GameEngine::init()
{
    _achievements = CCArray::createWithContentsOfFile(kAchievementsFileName);
    _achievements->retain();

    return true;
}

void GameEngine::startTutorial(bool startGame)
{
    _startWithTutorial = startGame;
    CCTransitionFade *transition = CCTransitionFade::create(kTransitionDuration, TutorialScene::scene());
    CCDirector::sharedDirector()->replaceScene(transition);
}

void GameEngine::finishTutorial()
{
    if (_startWithTutorial) {
        startNewGame();
    }
    else {
        CCTransitionFade *transition = CCTransitionFade::create(kTransitionDuration, TitleScene::scene());
        CCDirector::sharedDirector()->replaceScene(transition);
    }
}

void GameEngine::startNewGame()
{
    _score = 0;
    _stamina = StaminaMax;
    _foundItems.clear();

    CCDirector *director = CCDirector::sharedDirector();
    CCTransitionFade *transition = CCTransitionFade::create(kTransitionDuration, GameScene::scene());
    director->replaceScene(transition);

    director->getScheduler()->scheduleSelector(schedule_selector(GameEngine::tick), this, kGameTickInterval, false);
}

void GameEngine::finishGame()
{
    CCDirector *director = CCDirector::sharedDirector();

    director->getScheduler()->unscheduleSelector(schedule_selector(GameEngine::tick), this);

    GameScene *gameScene = (GameScene *)director->getRunningScene()->getChildren()->objectAtIndex(0);
    gameScene->finishAnimations();

    CocosDenshion::SimpleAudioEngine::sharedEngine()->playEffect(SEGameOver);

    registerFoundItemCount();

    director->getScheduler()->scheduleSelector(schedule_selector(GameEngine::showResult), this, 0, 0, kWaitForResultDuration, false);

    registerActivities();
}

void GameEngine::tick()
{
    _stamina -= kStaminaConsumption;
    _score += kSurvivePoint;

    if (_stamina <= 0) {
        this->finishGame();
    }
}

void GameEngine::registerFoundItemCount()
{
    map<hiberlite::sqlid_t, int>::iterator iterator = _foundItems.begin();

    while (iterator != _foundItems.end()) {
        hiberlite::sqlid_t itemID = (*iterator).first;
        Item item = _items.at(itemID - 1);
        int count = (*iterator).second;

        item->updateCount(item->count + count);
        item.save();

        iterator++;
    }
}

void GameEngine::registerActivities()
{
    GameCenter *gameCenter = GameCenter::sharedCenter();

    CCUserDefault *userDefault = CCUserDefault::sharedUserDefault();
    int currentHighScore = userDefault->getIntegerForKey(HighScoreKey, 0);
    string currentHighScoreChecksum = userDefault->getStringForKey(HighScoreChecksumKey, "");

    if (currentHighScoreChecksum != generateScoreChecksum(currentHighScore)) {
        currentHighScore = 0;
    }

    int highScore = _score;
    if (_score > currentHighScore) {
        userDefault->setIntegerForKey(HighScoreKey, _score);
        userDefault->setStringForKey(HighScoreChecksumKey, generateScoreChecksum(_score));
        userDefault->flush();
    }
    else {
        highScore = currentHighScore;
    }
    gameCenter->registerHighScore(highScore);

    vector<Achievement> completedAchievements;

    Achievement firstPlayAchievement;
    firstPlayAchievement.setName(AchievementFirstPlayName);
    firstPlayAchievement.setIOSAchievementID(AchievementFirstPlayAchievementIDIOS);
    firstPlayAchievement.setProcess(1);
    firstPlayAchievement.setGoal(1);
    completedAchievements.push_back(firstPlayAchievement);

    CCObject *object = NULL;
    CCARRAY_FOREACH(_achievements, object) {
        CCDictionary *achievementInfo = (CCDictionary *)object;

        int count = ((CCString *)achievementInfo->objectForKey("count"))->intValue();
        CCArray *itemIDs = (CCArray *)achievementInfo->objectForKey("item_ids");

        int sum = 0;
        CCObject *itemID = NULL;
        CCARRAY_FOREACH(itemIDs, itemID) {
            int id = ((CCString *)itemID)->intValue();
            Item item = _items.at(id - 1);
            sum += item->count;
        }

        Achievement achievement;
        achievement.setName(((CCString *)achievementInfo->objectForKey("name"))->getCString());
        achievement.setIOSAchievementID(((CCString *)achievementInfo->objectForKey("ios_achievement_id"))->getCString());
        achievement.setProcess(sum);
        achievement.setGoal(count);
        completedAchievements.push_back(achievement);
    }

    gameCenter->registerAchievements(&completedAchievements);
}

void GameEngine::showResult()
{
    CCTransitionFade *transition = CCTransitionFade::create(kTransitionDuration, ResultScene::scene());
    CCDirector::sharedDirector()->replaceScene(transition);
}

void GameEngine::showItemList()
{
    CCTransitionFade *transition = CCTransitionFade::create(kTransitionDuration, ItemListScene::scene());
    CCDirector::sharedDirector()->replaceScene(transition);
}

void GameEngine::showRanking()
{
    GameCenter::sharedCenter()->showRanking();
}

void GameEngine::showTitle()
{
    CCTransitionFade *transition = CCTransitionFade::create(kTransitionDuration, TitleScene::scene());
    CCDirector::sharedDirector()->replaceScene(transition);
}

void GameEngine::confirmResetSaveData()
{
    NotificationLayer *confirmLayer = NotificationLayer::create();
    confirmLayer->setTitle(MessageConfirmResetSaveDataTitle);
    confirmLayer->setNoticeMessage(MessageConfirmResetSaveDataText);
    confirmLayer->setNotificationType(NOTIFICATION_LAYER_YES_NO);
    confirmLayer->setActionTarget(NOTIFICATION_LAYER_ACTION_NO, CCDirector::sharedDirector(), menu_selector(CCDirector::popScene));
    confirmLayer->setActionTarget(NOTIFICATION_LAYER_ACTION_YES, this, menu_selector(GameEngine::resetSaveData));

    CCScene *scene = CCScene::create();
    scene->addChild(confirmLayer);
    CCDirector::sharedDirector()->pushScene(scene);
}

void GameEngine::resetSaveData()
{
    rebuildSaveData();

    CCUserDefault *userDefault = CCUserDefault::sharedUserDefault();
    userDefault->setBoolForKey(TutorialStateKey, false);
    userDefault->setIntegerForKey(HighScoreKey, 0);
    userDefault->setStringForKey(HighScoreChecksumKey, "");
    userDefault->flush();

    NotificationLayer *noticeLayer = NotificationLayer::create();
    noticeLayer->setTitle(MessageConfirmResetSaveDataTitle);
    noticeLayer->setNoticeMessage(MessageCompleteResetSaveDataText);
    noticeLayer->setNotificationType(NOTIFICATION_LAYER_OK_ONLY);
    noticeLayer->setActionTarget(NOTIFICATION_LAYER_ACTION_OK, CCDirector::sharedDirector(), menu_selector(CCDirector::popScene));

    CCScene *scene = CCScene::create();
    scene->addChild(noticeLayer);
    CCDirector::sharedDirector()->replaceScene(scene);
}

bool GameEngine::needsTutorial()
{
    CCUserDefault *userDefault = CCUserDefault::sharedUserDefault();
    bool tutorialDone = userDefault->getBoolForKey(TutorialStateKey, false);
    if (!tutorialDone) {
        userDefault->setBoolForKey(TutorialStateKey, true);
        userDefault->flush();
        return true;
    }
    return false;
}

int GameEngine::getScore()
{
    return _score;
}

int GameEngine::getStamina()
{
    return _stamina;
}

void GameEngine::addScore(int score)
{
    _score += score;
}

void GameEngine::addStamina(int stamina)
{
    if (_stamina + stamina > StaminaMax) {
        _stamina = StaminaMax;
    }
    else {
        _stamina += stamina;
    }
}

void GameEngine::loadSaveData()
{
    CCFileUtils *fileUtils = CCFileUtils::sharedFileUtils();
    bool forceRebuildSaveData = false;

    string saveFilePath = fileUtils->getWritablePath().append(kSavefileName);
    if (forceRebuildSaveData || !fileUtils->isFileExist(saveFilePath)) {
        copyInitialData(saveFilePath);
    }

    _db.open(saveFilePath);

    _items = _db.getAllBeans<_Item>();
    for (int i=0; i<_items.size(); i++) {
        if (!_items.at(i)->validate()) {
            CCLog("validation error!!");

            rebuildSaveData();

            NotificationLayer *noticeLayer = NotificationLayer::create();
            noticeLayer->setTitle(MessageInvalidDataTitle);
            noticeLayer->setNoticeMessage(MessageInvalidDataText);
            noticeLayer->setNotificationType(NOTIFICATION_LAYER_OK_ONLY);
            noticeLayer->setActionTarget(NOTIFICATION_LAYER_ACTION_OK, CCDirector::sharedDirector(), menu_selector(CCDirector::popScene));

            CCScene *scene = CCScene::create();
            scene->addChild(noticeLayer);
            CCDirector::sharedDirector()->pushScene(scene);

            return;
        }
    }
}

void GameEngine::rebuildSaveData()
{
    CCFileUtils *fileUtils = CCFileUtils::sharedFileUtils();

    _db.close();
    _items.clear();

    string saveFilePath = fileUtils->getWritablePath().append(kSavefileName);
    copyInitialData(saveFilePath);

    _db.open(saveFilePath);
    _items = _db.getAllBeans<_Item>();
}

void GameEngine::copyInitialData(string saveFilePath)
{
    CCFileUtils *fileUtils = CCFileUtils::sharedFileUtils();

    string initDBFilePath = fileUtils->fullPathForFilename("init.db");

    unsigned long nSize = 0;
    unsigned char* buffer = fileUtils->getFileData(initDBFilePath.c_str(), "rb", &nSize);

    if (buffer != NULL && nSize > 0) {
        FILE *dest = fopen(saveFilePath.c_str(), "wb");
        unsigned long result = fwrite(buffer, sizeof(char), nSize, dest);
        if (result < nSize) {
            CCLog("copy savedata failed. %ld", result);
        }
        fclose(dest);
    }
    CC_SAFE_DELETE_ARRAY(buffer);
}

void GameEngine::foundItem(hiberlite::sqlid_t itemID)
{
    Item item = _items.at(itemID - 1);

    addScore(item->score);
    addStamina(item->stamina);

    if (_foundItems.find(itemID) == _foundItems.end()) {
        _foundItems[itemID] = 1;
    }
    else {
        _foundItems[itemID] += 1;
    }
}

string GameEngine::generateScoreChecksum(int score)
{
    char input[64];
    unsigned char digest[SHA1DigestLength];
    char buf[ChecksumLength];

    sprintf(input, "%d:%s", score, ScoreChecksumSalt);

    SHA1 sha1;
    sha1.addBytes((unsigned char *)input, strlen(input));
    sha1.getDigest(digest, SHA1DigestLength);
    sprintf(buf, "%02x%02x%02x%02x", digest[0], digest[1], digest[2], digest[3]);

    return string(buf);
}

vector<Item> *GameEngine::getItems()
{
    return &_items;
}

map<hiberlite::sqlid_t, int> *GameEngine::getFoundItems()
{
    return &_foundItems;
}<|endoftext|>


<commit_before>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/fnet/fnet.h>
#include "dummy.h"

TEST("lock speed") {
  FastOS_Time      start;
  FastOS_Time       stop;
  DummyLock        dummy;
  std::mutex        lock;
  double       dummyTime;
  double      actualTime;
  double        overhead;
  uint32_t             i;

  start.SetNow();
  for (i = 0; i < 1000000; i++) {
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
  }
  stop.SetNow();
  stop -= start;
  dummyTime = stop.MilliSecs();

  fprintf(stderr,
          "10M dummy lock/unlock: %f ms (%1.2f/ms)\n",
          dummyTime, 10000000.0 / dummyTime);

  start.SetNow();
  for (i = 0; i < 1000000; i++) {
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
  }
  stop.SetNow();
  stop -= start;
  actualTime = stop.MilliSecs();

  fprintf(stderr,
          "10M actual lock/unlock: %f ms (%1.2f/ms)\n",
          stop.MilliSecs(), 10000000.0 / stop.MilliSecs());

  overhead = (actualTime - dummyTime) / 10000.0;

  fprintf(stderr,
          "approx overhead per lock/unlock: %f microseconds\n",
          overhead);

  //---------------------------------------------------------------------------

  start.SetNow();
  for (i = 0; i < 1000000; i++) {
      std::mutex lock0;
      std::mutex lock1;
      std::mutex lock2;
      std::mutex lock3;
      std::mutex lock4;
      std::mutex lock5;
      std::mutex lock6;
      std::mutex lock7;
      std::mutex lock8;
      std::mutex lock9;
  }
  stop.SetNow();
  stop -= start;
  fprintf(stderr, "10M mutex create/destroy %f ms (%1.2f/ms)\n",
      stop.MilliSecs(), 10000000.0 / stop.MilliSecs());

  //---------------------------------------------------------------------------

  start.SetNow();
  for (i = 0; i < 1000000; i++) {
      std::condition_variable cond0;
      std::condition_variable cond1;
      std::condition_variable cond2;
      std::condition_variable cond3;
      std::condition_variable cond4;
      std::condition_variable cond5;
      std::condition_variable cond6;
      std::condition_variable cond7;
      std::condition_variable cond8;
      std::condition_variable cond9;
  }
  stop.SetNow();
  stop -= start;
  fprintf(stderr, "10M cond create/destroy %f ms (%1.2f/ms)\n",
      stop.MilliSecs(), 10000000.0 / stop.MilliSecs());

  //---------------------------------------------------------------------------

  start.SetNow();
  for (i = 0; i < 1000000; i++) {
      DummyObj dummy0;
      DummyObj dummy1;
      DummyObj dummy2;
      DummyObj dummy3;
      DummyObj dummy4;
      DummyObj dummy5;
      DummyObj dummy6;
      DummyObj dummy7;
      DummyObj dummy8;
      DummyObj dummy9;
  }
  stop.SetNow();
  stop -= start;
  fprintf(stderr, "10M dummy create/destroy %f ms (%1.2f/ms)\n",
      stop.MilliSecs(), 10000000.0 / stop.MilliSecs());

  //---------------------------------------------------------------------------

  start.SetNow();
  for (i = 0; i < 1000000; i++) {
      DummyObj *dummy0 = new DummyObj();
      DummyObj *dummy1 = new DummyObj();
      DummyObj *dummy2 = new DummyObj();
      DummyObj *dummy3 = new DummyObj();
      DummyObj *dummy4 = new DummyObj();
      DummyObj *dummy5 = new DummyObj();
      DummyObj *dummy6 = new DummyObj();
      DummyObj *dummy7 = new DummyObj();
      DummyObj *dummy8 = new DummyObj();
      DummyObj *dummy9 = new DummyObj();
      delete dummy9;
      delete dummy8;
      delete dummy7;
      delete dummy6;
      delete dummy5;
      delete dummy4;
      delete dummy3;
      delete dummy2;
      delete dummy1;
      delete dummy0;
  }
  stop.SetNow();
  stop -= start;
  fprintf(stderr, "10M dummy new/delete %f ms (%1.2f/ms)\n",
          stop.MilliSecs(), 10000000.0 / stop.MilliSecs());

  //---------------------------------------------------------------------------
}

TEST_MAIN() { TEST_RUN_ALL(); }
<commit_msg>added benchmark of spinlock<commit_after>// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#include <vespa/vespalib/testkit/test_kit.h>
#include <vespa/fnet/fnet.h>
#include "dummy.h"

class SpinLock {
private:
    std::atomic_flag _lock;
public:
    SpinLock() : _lock(false) {}
    void lock() {
        while (_lock.test_and_set(std::memory_order_acquire)) {
            // spin
        }
    }
    void unlock() { _lock.clear(std::memory_order_release); }
};

TEST("lock speed") {
  FastOS_Time      start;
  FastOS_Time       stop;
  DummyLock        dummy;
  std::mutex        lock;
  SpinLock          spin;
  double       dummyTime;
  double      actualTime;
  double        overhead;
  double   spin_overhead;
  double     spin_factor;
  uint32_t             i;

  start.SetNow();
  for (i = 0; i < 1000000; i++) {
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
    dummy.Lock();
    dummy.Unlock();
  }
  stop.SetNow();
  stop -= start;
  dummyTime = stop.MilliSecs();

  fprintf(stderr,
          "10M dummy lock/unlock: %f ms (%1.2f/ms)\n",
          dummyTime, 10000000.0 / dummyTime);

  start.SetNow();
  for (i = 0; i < 1000000; i++) {
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
    lock.lock();
    lock.unlock();
  }
  stop.SetNow();
  stop -= start;
  actualTime = stop.MilliSecs();

  fprintf(stderr,
          "10M actual lock/unlock: %f ms (%1.2f/ms)\n",
          stop.MilliSecs(), 10000000.0 / stop.MilliSecs());

  overhead = (actualTime - dummyTime) / 10000.0;

  start.SetNow();
  for (i = 0; i < 1000000; i++) {
    spin.lock();
    spin.unlock();
    spin.lock();
    spin.unlock();
    spin.lock();
    spin.unlock();
    spin.lock();
    spin.unlock();
    spin.lock();
    spin.unlock();
    spin.lock();
    spin.unlock();
    spin.lock();
    spin.unlock();
    spin.lock();
    spin.unlock();
    spin.lock();
    spin.unlock();
    spin.lock();
    spin.unlock();
  }
  stop.SetNow();
  stop -= start;
  actualTime = stop.MilliSecs();

  fprintf(stderr,
          "10M actual (spin) lock/unlock: %f ms (%1.2f/ms)\n",
          stop.MilliSecs(), 10000000.0 / stop.MilliSecs());

  spin_overhead = (actualTime - dummyTime) / 10000.0;

  spin_factor = overhead / spin_overhead;

  fprintf(stderr,
          "approx overhead per lock/unlock: %f microseconds\n",
          overhead);

  fprintf(stderr,
          "approx overhead per lock/unlock (spin): %f microseconds\n",
          spin_overhead);

  fprintf(stderr,
          "spinlocks are %f times faster\n",
          spin_factor);

  //---------------------------------------------------------------------------

  start.SetNow();
  for (i = 0; i < 1000000; i++) {
      std::mutex lock0;
      std::mutex lock1;
      std::mutex lock2;
      std::mutex lock3;
      std::mutex lock4;
      std::mutex lock5;
      std::mutex lock6;
      std::mutex lock7;
      std::mutex lock8;
      std::mutex lock9;
  }
  stop.SetNow();
  stop -= start;
  fprintf(stderr, "10M mutex create/destroy %f ms (%1.2f/ms)\n",
      stop.MilliSecs(), 10000000.0 / stop.MilliSecs());

  //---------------------------------------------------------------------------

  start.SetNow();
  for (i = 0; i < 1000000; i++) {
      std::condition_variable cond0;
      std::condition_variable cond1;
      std::condition_variable cond2;
      std::condition_variable cond3;
      std::condition_variable cond4;
      std::condition_variable cond5;
      std::condition_variable cond6;
      std::condition_variable cond7;
      std::condition_variable cond8;
      std::condition_variable cond9;
  }
  stop.SetNow();
  stop -= start;
  fprintf(stderr, "10M cond create/destroy %f ms (%1.2f/ms)\n",
      stop.MilliSecs(), 10000000.0 / stop.MilliSecs());

  //---------------------------------------------------------------------------

  start.SetNow();
  for (i = 0; i < 1000000; i++) {
      DummyObj dummy0;
      DummyObj dummy1;
      DummyObj dummy2;
      DummyObj dummy3;
      DummyObj dummy4;
      DummyObj dummy5;
      DummyObj dummy6;
      DummyObj dummy7;
      DummyObj dummy8;
      DummyObj dummy9;
  }
  stop.SetNow();
  stop -= start;
  fprintf(stderr, "10M dummy create/destroy %f ms (%1.2f/ms)\n",
      stop.MilliSecs(), 10000000.0 / stop.MilliSecs());

  //---------------------------------------------------------------------------

  start.SetNow();
  for (i = 0; i < 1000000; i++) {
      DummyObj *dummy0 = new DummyObj();
      DummyObj *dummy1 = new DummyObj();
      DummyObj *dummy2 = new DummyObj();
      DummyObj *dummy3 = new DummyObj();
      DummyObj *dummy4 = new DummyObj();
      DummyObj *dummy5 = new DummyObj();
      DummyObj *dummy6 = new DummyObj();
      DummyObj *dummy7 = new DummyObj();
      DummyObj *dummy8 = new DummyObj();
      DummyObj *dummy9 = new DummyObj();
      delete dummy9;
      delete dummy8;
      delete dummy7;
      delete dummy6;
      delete dummy5;
      delete dummy4;
      delete dummy3;
      delete dummy2;
      delete dummy1;
      delete dummy0;
  }
  stop.SetNow();
  stop -= start;
  fprintf(stderr, "10M dummy new/delete %f ms (%1.2f/ms)\n",
          stop.MilliSecs(), 10000000.0 / stop.MilliSecs());

  //---------------------------------------------------------------------------
}

TEST_MAIN() { TEST_RUN_ALL(); }
<|endoftext|>


<commit_before>#include "FrameMetaData.h"

namespace FrameProcessor {

    FrameMetaData::FrameMetaData(const long long& frame_number,
                                   const std::string &dataset_name,
                                   const DataType &data_type,
                                   const std::string &acquisition_ID,
                                   const std::vector<unsigned long long> &dimensions,
                                   const CompressionType &compression_type) :
            frame_number_(frame_number),
            dataset_name_(dataset_name),
            data_type_(data_type),
            acquisition_ID_(acquisition_ID),
            dimensions_(dimensions),
            compression_type_(compression_type),
            frame_offset_(0),
            logger(log4cxx::Logger::getLogger("FP.FrameMetaData")) {
      logger->setLevel(log4cxx::Level::getAll());
    }

    FrameMetaData::FrameMetaData() :
            frame_number_(-1),
            dataset_name_(""),
            data_type_(raw_8bit),
            compression_type_(no_compression),
            frame_offset_(0),
            logger(log4cxx::Logger::getLogger("FP.FrameMetaData")) {
      logger->setLevel(log4cxx::Level::getAll());
    }

    FrameMetaData::FrameMetaData(const FrameMetaData &frame) {
      frame_number_ = frame.frame_number_;
      dataset_name_ = frame.dataset_name_;
      data_type_ = frame.data_type_;
      acquisition_ID_ = frame.acquisition_ID_;
      dimensions_ = frame.dimensions_;
      compression_type_ = frame.compression_type_;
      parameters_ = frame.parameters_;
      frame_offset_ = frame.frame_offset_;
      logger = frame.logger;
    }

    /** Get frame parameters
     * @return std::map <std::string, boost::any>  map
     */
    const std::map <std::string, boost::any> &FrameMetaData::get_parameters() const {
      return this->parameters_;
    };

    /** Return frame number
     * @return long long - frame number
     */
    long long FrameMetaData::get_frame_number() const {
      return this->frame_number_;
    }

    /** Set frame number
     * @param long long - frame number
     */
    void FrameMetaData::set_frame_number(const long long& frame_number) {
      this->frame_number_ = frame_number;
    }

    /** Return dataset name
     * @return std::string - dataset name
     */
    const std::string &FrameMetaData::get_dataset_name() const {
      return this->dataset_name_;
    }

    /** Set dataset name
     * @param std::string dataset_name - name of dataset
     */
    void FrameMetaData::set_dataset_name(const std::string &dataset_name) {
      this->dataset_name_ = dataset_name;
    }

    /** Return data type
     * @return DataType - data type
     */
    DataType FrameMetaData::get_data_type() const {
      return this->data_type_;
    }

    /** Set data type
     * @param DataType - data type
     */
    void FrameMetaData::set_data_type(DataType data_type) {
      this->data_type_ = data_type;
    }

    /** Return acquistion ID
     * @return std::string acquisition ID
     */
    const std::string &FrameMetaData::get_acquisition_ID() const {
      return this->acquisition_ID_;
    }

    /** Set acquisition ID
     * @param std::string acquisition_ID
     */
    void FrameMetaData::set_acquisition_ID(const std::string &acquisition_ID) {
      this->acquisition_ID_ = acquisition_ID;
    }

    /** Return dimensions
     * @return dimensions
     */
    const dimensions_t &FrameMetaData::get_dimensions() const {
      return this->dimensions_;
    }

    /** Set dimensions
     * @param dimensions_t dimensions
     */
    void FrameMetaData::set_dimensions(const dimensions_t &dimensions) {
      this->dimensions_ = dimensions;
    }

    /** Return compression type
     * @return compression type
     */
    CompressionType FrameMetaData::get_compression_type() const {
      return this->compression_type_;
    }

    /** Set compression type
     * @ param compression_type compression type
     */
    void FrameMetaData::set_compression_type(CompressionType compression_type) {
      this->compression_type_ = compression_type;
    }

    /** Return frame offset
     * @return int64_t frame offset
     */
    int64_t FrameMetaData::get_frame_offset() const {
      return this->frame_offset_;
    }

    /** Set frame offset
     * @param int64_t new offset
     */
    void FrameMetaData::set_frame_offset(const int64_t &offset) {
      this->frame_offset_ = offset;
    }

    /** Adjust frame offset by increment
      * @param increment to adjust offset by
      */
    void FrameMetaData::adjust_frame_offset(const int64_t &increment) {
      this->frame_offset_ += increment;
    }

}
<commit_msg>updating default FrameMetaData constructor arguments<commit_after>#include "FrameMetaData.h"

namespace FrameProcessor {

    FrameMetaData::FrameMetaData(const long long& frame_number,
                                   const std::string &dataset_name,
                                   const DataType &data_type,
                                   const std::string &acquisition_ID,
                                   const std::vector<unsigned long long> &dimensions,
                                   const CompressionType &compression_type) :
            frame_number_(frame_number),
            dataset_name_(dataset_name),
            data_type_(data_type),
            acquisition_ID_(acquisition_ID),
            dimensions_(dimensions),
            compression_type_(compression_type),
            frame_offset_(0),
            logger(log4cxx::Logger::getLogger("FP.FrameMetaData")) {
      logger->setLevel(log4cxx::Level::getAll());
    }

    FrameMetaData::FrameMetaData() :
            frame_number_(-1),
            dataset_name_(""),
            data_type_(raw_unknown),
            compression_type_(unknown_compression),
            frame_offset_(0),
            logger(log4cxx::Logger::getLogger("FP.FrameMetaData")) {
      logger->setLevel(log4cxx::Level::getAll());
    }

    FrameMetaData::FrameMetaData(const FrameMetaData &frame) {
      frame_number_ = frame.frame_number_;
      dataset_name_ = frame.dataset_name_;
      data_type_ = frame.data_type_;
      acquisition_ID_ = frame.acquisition_ID_;
      dimensions_ = frame.dimensions_;
      compression_type_ = frame.compression_type_;
      parameters_ = frame.parameters_;
      frame_offset_ = frame.frame_offset_;
      logger = frame.logger;
    }

    /** Get frame parameters
     * @return std::map <std::string, boost::any>  map
     */
    const std::map <std::string, boost::any> &FrameMetaData::get_parameters() const {
      return this->parameters_;
    };

    /** Return frame number
     * @return long long - frame number
     */
    long long FrameMetaData::get_frame_number() const {
      return this->frame_number_;
    }

    /** Set frame number
     * @param long long - frame number
     */
    void FrameMetaData::set_frame_number(const long long& frame_number) {
      this->frame_number_ = frame_number;
    }

    /** Return dataset name
     * @return std::string - dataset name
     */
    const std::string &FrameMetaData::get_dataset_name() const {
      return this->dataset_name_;
    }

    /** Set dataset name
     * @param std::string dataset_name - name of dataset
     */
    void FrameMetaData::set_dataset_name(const std::string &dataset_name) {
      this->dataset_name_ = dataset_name;
    }

    /** Return data type
     * @return DataType - data type
     */
    DataType FrameMetaData::get_data_type() const {
      return this->data_type_;
    }

    /** Set data type
     * @param DataType - data type
     */
    void FrameMetaData::set_data_type(DataType data_type) {
      this->data_type_ = data_type;
    }

    /** Return acquistion ID
     * @return std::string acquisition ID
     */
    const std::string &FrameMetaData::get_acquisition_ID() const {
      return this->acquisition_ID_;
    }

    /** Set acquisition ID
     * @param std::string acquisition_ID
     */
    void FrameMetaData::set_acquisition_ID(const std::string &acquisition_ID) {
      this->acquisition_ID_ = acquisition_ID;
    }

    /** Return dimensions
     * @return dimensions
     */
    const dimensions_t &FrameMetaData::get_dimensions() const {
      return this->dimensions_;
    }

    /** Set dimensions
     * @param dimensions_t dimensions
     */
    void FrameMetaData::set_dimensions(const dimensions_t &dimensions) {
      this->dimensions_ = dimensions;
    }

    /** Return compression type
     * @return compression type
     */
    CompressionType FrameMetaData::get_compression_type() const {
      return this->compression_type_;
    }

    /** Set compression type
     * @ param compression_type compression type
     */
    void FrameMetaData::set_compression_type(CompressionType compression_type) {
      this->compression_type_ = compression_type;
    }

    /** Return frame offset
     * @return int64_t frame offset
     */
    int64_t FrameMetaData::get_frame_offset() const {
      return this->frame_offset_;
    }

    /** Set frame offset
     * @param int64_t new offset
     */
    void FrameMetaData::set_frame_offset(const int64_t &offset) {
      this->frame_offset_ = offset;
    }

    /** Adjust frame offset by increment
      * @param increment to adjust offset by
      */
    void FrameMetaData::adjust_frame_offset(const int64_t &increment) {
      this->frame_offset_ += increment;
    }

}
<|endoftext|>