<commit_before>/*
 * Copyright 2010-2012 Esrille Inc.
 *
 * 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 "NodeImp.h"
#include "DocumentImp.h"
#include "MutationEventImp.h"
#include "ElementImp.h"
#include "NodeListImp.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

//
// Tree management
//

NodeImp* NodeImp::removeChild(NodeImp* item)
{
    NodeImp* next = item->nextSibling;
    NodeImp* prev = item->previousSibling;
    if (!next)
        lastChild = prev;
    else
        next->previousSibling = prev;
    if (!prev)
        firstChild = next;
    else
        prev->nextSibling = next;
    item->parentNode = 0;
    --childCount;
    return item;
}

NodeImp* NodeImp::insertBefore(NodeImp* item, NodeImp* after)
{
    item->previousSibling = after->previousSibling;
    item->nextSibling = after;
    after->previousSibling = item;
    if (!item->previousSibling)
        firstChild = item;
    else
        item->previousSibling->nextSibling = item;
    item->parentNode = this;
    ++childCount;
    return item;
}

NodeImp* NodeImp::appendChild(NodeImp* item)
{
    NodeImp* prev = lastChild;
    if (!prev)
        firstChild = item;
    else
        prev->nextSibling = item;
    item->previousSibling = prev;
    item->nextSibling = 0;
    lastChild = item;
    item->parentNode = this;
    ++childCount;
    return item;
}

void NodeImp::eval()
{
}

void NodeImp::setOwnerDocument(DocumentImp* document)
{
    assert(!ownerDocument);
    ownerDocument = document;
}

// Node
unsigned short NodeImp::getNodeType()
{
    // TODO: SHOUD NOT REACH HERE
    return 0;
}

std::u16string NodeImp::getNodeName()
{
    return nodeName;
}

Nullable<std::u16string> NodeImp::getBaseURI()
{
    // TODO: implement me!
    return u"";
}

Document NodeImp::getOwnerDocument()
{
    return ownerDocument;
}

Node NodeImp::getParentNode()
{
    return parentNode;
}

Element NodeImp::getParentElement()
{
    return dynamic_cast<ElementImp*>(parentNode);
}

bool NodeImp::hasChildNodes()
{
    return firstChild;
}

NodeList NodeImp::getChildNodes()
{
    return new(std::nothrow) NodeListImp(this);
}

Node NodeImp::getFirstChild()
{
    return firstChild;
}

Node NodeImp::getLastChild()
{
    return lastChild;
}

Node NodeImp::getPreviousSibling()
{
    return previousSibling;
}

Node NodeImp::getNextSibling()
{
    return nextSibling;
}

unsigned short NodeImp::compareDocumentPosition(Node other)
{
    // TODO: implement me!
    return 0;
}

Nullable<std::u16string> NodeImp::getNodeValue()
{
    // TODO: implement me!
    return u"";
}

void NodeImp::setNodeValue(Nullable<std::u16string> nodeValue)
{
    // TODO: implement me!
}

Nullable<std::u16string> NodeImp::getTextContent()
{
    return u"";  // TODO: return null instead
}

void NodeImp::setTextContent(Nullable<std::u16string> textContent)
{
    // TODO: implement me!
}

Node NodeImp::insertBefore(Node newChild, Node refChild)
{
    if (!newChild)
        return newChild;
    if (!refChild)
        return appendChild(newChild);
    if (newChild != refChild) {
        Document ownerOfChild = newChild.getOwnerDocument();
        if (ownerOfChild != getOwnerDocument() && ownerOfChild != *this)
            throw DOMException(DOMException::WRONG_DOCUMENT_ERR);
        if (refChild.getParentNode() != *this)
            throw DOMException(DOMException::NOT_FOUND_ERR);
        if (NodeImp* child = dynamic_cast<NodeImp*>(newChild.self())) {
            if (child == this || child->isAncestorOf(this))
                throw DOMException(DOMException::HIERARCHY_REQUEST_ERR);
            if (NodeImp* ref = dynamic_cast<NodeImp*>(refChild.self())) {
                child->retain_();
                if (child->parentNode) {
                    child->parentNode->removeChild(child);
                    child->release_();
                }
                insertBefore(child, ref);
            }
        }
    }
    return newChild;
}

Node NodeImp::replaceChild(Node newChild, Node oldChild)
{
    if (!newChild)
        return oldChild;
    if (!oldChild || oldChild.getParentNode() != *this)
        throw DOMException(DOMException::NOT_FOUND_ERR);
    if (newChild != oldChild) {
        Document ownerOfChild = newChild.getOwnerDocument();
        if (ownerOfChild != getOwnerDocument() && ownerOfChild != *this)
            throw DOMException(DOMException::WRONG_DOCUMENT_ERR);
        if (NodeImp* child = dynamic_cast<NodeImp*>(newChild.self())) {
            if (child == this || child->isAncestorOf(this))
                throw DOMException(DOMException::HIERARCHY_REQUEST_ERR);
            if (NodeImp* ref = dynamic_cast<NodeImp*>(oldChild.self())) {
                child->retain_();
                if (child->parentNode) {
                    child->parentNode->removeChild(child);
                    child->release_();
                }
                insertBefore(child, ref);
                removeChild(ref);
                ref->release_();
            }
        }
    }
    return oldChild;
}

Node NodeImp::removeChild(Node oldChild)
{
    if (!oldChild)
        throw DOMException(DOMException::NOT_FOUND_ERR);
    if (NodeImp* child = dynamic_cast<NodeImp*>(oldChild.self())) {
        if (child->parentNode != this)
            throw DOMException(DOMException::NOT_FOUND_ERR);
        removeChild(child);
        child->release_();

        events::MutationEvent event = new(std::nothrow) MutationEventImp;
        event.initMutationEvent(u"DOMNodeRemoved",
                                true, false, this, u"", u"", u"", 0);
        this->dispatchEvent(event);

    }
    return oldChild;
}

Node NodeImp::appendChild(Node newChild)
{
    if (!newChild)
        return newChild;
    Document ownerOfChild = newChild.getOwnerDocument();
    if (ownerOfChild != getOwnerDocument() && ownerOfChild != *this)
        throw DOMException(DOMException::WRONG_DOCUMENT_ERR);
    if (NodeImp* child = dynamic_cast<NodeImp*>(newChild.self())) {
        if (child == this || child->isAncestorOf(this))
            throw DOMException(DOMException::HIERARCHY_REQUEST_ERR);
        // TODO: case newChild is a DocumentFragment
        child->retain_();
        if (child->parentNode) {
            child->parentNode->removeChild(child);
            child->release_();
        }
        appendChild(child);
    }  // TODO: else ...
    return newChild;
}

Node NodeImp::cloneNode(bool deep)
{
    return new(std::nothrow) NodeImp(this, deep);
}

bool NodeImp::isSameNode(Node other)
{
    return other == *this;
}

bool NodeImp::isEqualNode(Node arg)
{
    // TODO: implement me!
    return 0;
}

std::u16string NodeImp::lookupPrefix(std::u16string namespaceURI)
{
    // TODO: implement me!
    return u"";
}

std::u16string NodeImp::lookupNamespaceURI(Nullable<std::u16string> prefix)
{
    // TODO: implement me!
    return u"";
}

bool NodeImp::isDefaultNamespace(std::u16string namespaceURI)
{
    // TODO: implement me!
    return 0;
}

NodeImp::NodeImp(DocumentImp* ownerDocument) :
    ownerDocument(ownerDocument),
    parentNode(0),
    firstChild(0),
    lastChild(0),
    previousSibling(0),
    nextSibling(0),
    childCount(0)
{
}

NodeImp::NodeImp(NodeImp* org, bool deep) :
    ObjectMixin(org),
    ownerDocument(0),
    parentNode(0),
    firstChild(0),
    lastChild(0),
    previousSibling(0),
    nextSibling(0),
    childCount(0),
    nodeName(org->nodeName)
{
    setOwnerDocument(org->ownerDocument);
    if (!deep)
        return;
    for (NodeImp* node = org->firstChild; node; node = node->nextSibling) {
        Node clone = node->cloneNode(true);
        appendChild(clone);
    }
}

NodeImp::~NodeImp()
{
    assert(0 == count_());
    while (0 < childCount)
        removeChild(getFirstChild());
}

}}}}  // org::w3c::dom::bootstrap
<commit_msg>(NodeImp::removeChild) : Prevent dispatching an event from the destructor.<commit_after>/*
 * Copyright 2010-2012 Esrille Inc.
 *
 * 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 "NodeImp.h"
#include "DocumentImp.h"
#include "MutationEventImp.h"
#include "ElementImp.h"
#include "NodeListImp.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

//
// Tree management
//

NodeImp* NodeImp::removeChild(NodeImp* item)
{
    NodeImp* next = item->nextSibling;
    NodeImp* prev = item->previousSibling;
    if (!next)
        lastChild = prev;
    else
        next->previousSibling = prev;
    if (!prev)
        firstChild = next;
    else
        prev->nextSibling = next;
    item->parentNode = 0;
    --childCount;
    return item;
}

NodeImp* NodeImp::insertBefore(NodeImp* item, NodeImp* after)
{
    item->previousSibling = after->previousSibling;
    item->nextSibling = after;
    after->previousSibling = item;
    if (!item->previousSibling)
        firstChild = item;
    else
        item->previousSibling->nextSibling = item;
    item->parentNode = this;
    ++childCount;
    return item;
}

NodeImp* NodeImp::appendChild(NodeImp* item)
{
    NodeImp* prev = lastChild;
    if (!prev)
        firstChild = item;
    else
        prev->nextSibling = item;
    item->previousSibling = prev;
    item->nextSibling = 0;
    lastChild = item;
    item->parentNode = this;
    ++childCount;
    return item;
}

void NodeImp::eval()
{
}

void NodeImp::setOwnerDocument(DocumentImp* document)
{
    assert(!ownerDocument);
    ownerDocument = document;
}

// Node
unsigned short NodeImp::getNodeType()
{
    // TODO: SHOUD NOT REACH HERE
    return 0;
}

std::u16string NodeImp::getNodeName()
{
    return nodeName;
}

Nullable<std::u16string> NodeImp::getBaseURI()
{
    // TODO: implement me!
    return u"";
}

Document NodeImp::getOwnerDocument()
{
    return ownerDocument;
}

Node NodeImp::getParentNode()
{
    return parentNode;
}

Element NodeImp::getParentElement()
{
    return dynamic_cast<ElementImp*>(parentNode);
}

bool NodeImp::hasChildNodes()
{
    return firstChild;
}

NodeList NodeImp::getChildNodes()
{
    return new(std::nothrow) NodeListImp(this);
}

Node NodeImp::getFirstChild()
{
    return firstChild;
}

Node NodeImp::getLastChild()
{
    return lastChild;
}

Node NodeImp::getPreviousSibling()
{
    return previousSibling;
}

Node NodeImp::getNextSibling()
{
    return nextSibling;
}

unsigned short NodeImp::compareDocumentPosition(Node other)
{
    // TODO: implement me!
    return 0;
}

Nullable<std::u16string> NodeImp::getNodeValue()
{
    // TODO: implement me!
    return u"";
}

void NodeImp::setNodeValue(Nullable<std::u16string> nodeValue)
{
    // TODO: implement me!
}

Nullable<std::u16string> NodeImp::getTextContent()
{
    return u"";  // TODO: return null instead
}

void NodeImp::setTextContent(Nullable<std::u16string> textContent)
{
    // TODO: implement me!
}

Node NodeImp::insertBefore(Node newChild, Node refChild)
{
    if (!newChild)
        return newChild;
    if (!refChild)
        return appendChild(newChild);
    if (newChild != refChild) {
        Document ownerOfChild = newChild.getOwnerDocument();
        if (ownerOfChild != getOwnerDocument() && ownerOfChild != *this)
            throw DOMException(DOMException::WRONG_DOCUMENT_ERR);
        if (refChild.getParentNode() != *this)
            throw DOMException(DOMException::NOT_FOUND_ERR);
        if (NodeImp* child = dynamic_cast<NodeImp*>(newChild.self())) {
            if (child == this || child->isAncestorOf(this))
                throw DOMException(DOMException::HIERARCHY_REQUEST_ERR);
            if (NodeImp* ref = dynamic_cast<NodeImp*>(refChild.self())) {
                child->retain_();
                if (child->parentNode) {
                    child->parentNode->removeChild(child);
                    child->release_();
                }
                insertBefore(child, ref);
            }
        }
    }
    return newChild;
}

Node NodeImp::replaceChild(Node newChild, Node oldChild)
{
    if (!newChild)
        return oldChild;
    if (!oldChild || oldChild.getParentNode() != *this)
        throw DOMException(DOMException::NOT_FOUND_ERR);
    if (newChild != oldChild) {
        Document ownerOfChild = newChild.getOwnerDocument();
        if (ownerOfChild != getOwnerDocument() && ownerOfChild != *this)
            throw DOMException(DOMException::WRONG_DOCUMENT_ERR);
        if (NodeImp* child = dynamic_cast<NodeImp*>(newChild.self())) {
            if (child == this || child->isAncestorOf(this))
                throw DOMException(DOMException::HIERARCHY_REQUEST_ERR);
            if (NodeImp* ref = dynamic_cast<NodeImp*>(oldChild.self())) {
                child->retain_();
                if (child->parentNode) {
                    child->parentNode->removeChild(child);
                    child->release_();
                }
                insertBefore(child, ref);
                removeChild(ref);
                ref->release_();
            }
        }
    }
    return oldChild;
}

Node NodeImp::removeChild(Node oldChild)
{
    if (!oldChild)
        throw DOMException(DOMException::NOT_FOUND_ERR);
    if (NodeImp* child = dynamic_cast<NodeImp*>(oldChild.self())) {
        if (child->parentNode != this)
            throw DOMException(DOMException::NOT_FOUND_ERR);
        removeChild(child);
        child->release_();
        if (0 < count_()) {  // Prevent dispatching an event from the destructor.
            events::MutationEvent event = new(std::nothrow) MutationEventImp;
            event.initMutationEvent(u"DOMNodeRemoved",
                                    true, false, this, u"", u"", u"", 0);
            this->dispatchEvent(event);
        }
    }
    return oldChild;
}

Node NodeImp::appendChild(Node newChild)
{
    if (!newChild)
        return newChild;
    Document ownerOfChild = newChild.getOwnerDocument();
    if (ownerOfChild != getOwnerDocument() && ownerOfChild != *this)
        throw DOMException(DOMException::WRONG_DOCUMENT_ERR);
    if (NodeImp* child = dynamic_cast<NodeImp*>(newChild.self())) {
        if (child == this || child->isAncestorOf(this))
            throw DOMException(DOMException::HIERARCHY_REQUEST_ERR);
        // TODO: case newChild is a DocumentFragment
        child->retain_();
        if (child->parentNode) {
            child->parentNode->removeChild(child);
            child->release_();
        }
        appendChild(child);
    }  // TODO: else ...
    return newChild;
}

Node NodeImp::cloneNode(bool deep)
{
    return new(std::nothrow) NodeImp(this, deep);
}

bool NodeImp::isSameNode(Node other)
{
    return other == *this;
}

bool NodeImp::isEqualNode(Node arg)
{
    // TODO: implement me!
    return 0;
}

std::u16string NodeImp::lookupPrefix(std::u16string namespaceURI)
{
    // TODO: implement me!
    return u"";
}

std::u16string NodeImp::lookupNamespaceURI(Nullable<std::u16string> prefix)
{
    // TODO: implement me!
    return u"";
}

bool NodeImp::isDefaultNamespace(std::u16string namespaceURI)
{
    // TODO: implement me!
    return 0;
}

NodeImp::NodeImp(DocumentImp* ownerDocument) :
    ownerDocument(ownerDocument),
    parentNode(0),
    firstChild(0),
    lastChild(0),
    previousSibling(0),
    nextSibling(0),
    childCount(0)
{
}

NodeImp::NodeImp(NodeImp* org, bool deep) :
    ObjectMixin(org),
    ownerDocument(0),
    parentNode(0),
    firstChild(0),
    lastChild(0),
    previousSibling(0),
    nextSibling(0),
    childCount(0),
    nodeName(org->nodeName)
{
    setOwnerDocument(org->ownerDocument);
    if (!deep)
        return;
    for (NodeImp* node = org->firstChild; node; node = node->nextSibling) {
        Node clone = node->cloneNode(true);
        appendChild(clone);
    }
}

NodeImp::~NodeImp()
{
    assert(0 == count_());
    while (0 < childCount)
        removeChild(getFirstChild());
}

}}}}  // org::w3c::dom::bootstrap
<|endoftext|>


<commit_before>#include "OptBase.h"

///@todo split this file into static and non-static

std::mutex
    OptBase::mutexQueueTodo,
    OptBase::mutexQueueCalculated,
    OptBase::mutexQueueFinished,
    OptBase::mutexPOptimizers;

std::queue< std::pair<OptValue, OptBase*> >
    OptBase::queueTodo,
    OptBase::queueCalculated,
    OptBase::queueFinished;

std::vector<OptBase*>
    OptBase::pOptimizers;

OptBase::OptBase(const std::vector<OptBoundary> &optBoundaries,
                 unsigned int maxCalculations,
                 CalculatorBase* pCalculator,
                 OptTarget optTarget) :
    maxCalculations(maxCalculations),
    currentCalculation(0), ///@todo or start at 1?
    optBoundaries(optBoundaries),
    pCalculator(pCalculator),
    optTarget(optTarget),
    targetValue(0.0)
{
    mutexPOptimizers.lock();
    pOptimizers.push_back(this);
    mutexPOptimizers.unlock();
}

OptBase::~OptBase()
{

}

bool OptBase::optimise() ///@todo split this method into two [#1 only put new value onto to-calc queue ||| #2 save the result and move to next queue]
{
    OptValue newOptValue;

    if(currentCalculation >= maxCalculations) ///@todo might have to fix this condition
        return false;

    if(currentCalculation == 0) ///@todo care in case currentCalculation gets initalised with 1
    {
        bestCalculation.result = bad_value();
    }

    if(true) ///@todo currently this is always true, allow algorithms to stop somehow
    {
        newOptValue = get_next_value();
        ///@todo put new value in todo queue
    }
    return true;
}

void OptBase::add_finished_calculation(OptValue optValue, OptBase* pOptBase)
{
    mutexPreviousCalculations.lock();
    previousCalculations.push_back(optValue);
    mutexPreviousCalculations.unlock();
    mutexQueueFinished.lock();
    queueFinished.push({optValue, pOptBase});
    mutexQueueFinished.unlock();

    if(result_better(optValue, bestCalculation))
        bestCalculation = optValue;
}

T OptBase::bad_value() const
{
    switch(optTarget)
    {
        case MINIMIZE:
            return std::numeric_limits<T>::max();

        case MAXIMIZE:
            return std::numeric_limits<T>::min();

        case APPROACH:
            if(targetValue > 0.0)
                return std::numeric_limits<T>::min();
            else
                return std::numeric_limits<T>::max();

        case DIVERGE:
            return targetValue;

        default: //MINIMIZE
            return std::numeric_limits<T>::max();
    }
}

bool OptBase::result_better(const OptValue &result, const OptValue &other) const
{
    switch(optTarget)
    {
        case MINIMIZE:
            return result.result < other.result;

        case MAXIMIZE:
            return result.result > other.result;

        case APPROACH:
            return abs(targetValue - result.result) < abs(targetValue - other.result);

        case DIVERGE:
            return abs(targetValue - result.result) > abs(targetValue - other.result);

        default: //MINIMIZE
            return result.result < other.result;
    }
}

void OptBase::run_optimisations(unsigned int maxThreads)
{
    ///@todo
    ///@todo this is a non-threaded solution and should be fixed

    //for each optimiser, start get_value

}

T OptBase::random_factor()
{
    return rand()/(T)(RAND_MAX); ///@todo make sure this is properly seeded
}

void OptBase::threaded_work()
{
    while(true) ///@todo there has to be a check whether there still are calculations
    {
        if(available_todo())
        {
            ///@todo possible race condition here. Make it that pop checks for availability itself (return bool and have the value be a reference which is changed bool pop(out) )
            ///@todo or add another mutex which only locks for this check mutex availabilityCheck
            std::pair <OptValue, OptBase*> todo = pop_todo();
            OptValue optValue = todo.first;
            OptBase* pOptBase = todo.second;

            pOptBase->pCalculator->calculate(optValue);

        }

        std::this_thread::sleep_for(std::chrono::milliseconds(10)); ///@todo sleep time must be defineable by library user [maybe add as paramter to run_optimisations]
    }

}

void OptBase::push_todo(OptValue optValue, OptBase* pOptBase)
{
    mutexQueueTodo.lock();
    queueTodo.push({optValue, pOptBase});
    mutexQueueTodo.unlock();
}

void OptBase::push_calculated(OptValue optValue, OptBase *pOptBase)
{
    mutexQueueCalculated.lock();
    queueCalculated.push({optValue, pOptBase});
    mutexQueueCalculated.unlock();
}

void OptBase::push_finished(OptValue optValue, OptBase *pOptBase)
{
    mutexQueueFinished.lock();
    queueFinished.push({optValue, pOptBase});
    mutexQueueFinished.unlock();
}

bool OptBase::available_todo()
{
    bool out(false);

    mutexQueueTodo.lock();
    out = !queueTodo.empty();
    mutexQueueTodo.unlock();

    return out;
}

bool OptBase::available_calculated()
{
    bool out(false);

    mutexQueueCalculated.lock();
    out = !queueCalculated.empty();
    mutexQueueCalculated.unlock();

    return out;
}

bool OptBase::available_finished()
{
    bool out(false);

    mutexQueueFinished.lock();
    out = !queueFinished.empty();
    mutexQueueFinished.unlock();

    return out;
}

std::pair<OptValue, OptBase*> OptBase::pop_todo()
{
    mutexQueueTodo.lock();
    auto out = queueTodo.front();
    queueTodo.pop();
    mutexQueueTodo.unlock();
    return out;
}

std::pair<OptValue, OptBase*> OptBase::pop_calculated()
{
    mutexQueueCalculated.lock();
    auto out = queueCalculated.front();
    queueCalculated.pop();
    mutexQueueCalculated.unlock();
    return out;
}

std::pair<OptValue, OptBase*> OptBase::pop_finished()
{
    mutexQueueFinished.lock();
    auto out = queueFinished.front();
    queueFinished.pop();
    mutexQueueFinished.unlock();
    return out;
}

<commit_msg>added logic for actually calculation the queues<commit_after>#include "OptBase.h"

///@todo split this file into static and non-static

std::mutex
    OptBase::mutexQueueTodo,
    OptBase::mutexQueueCalculated,
    OptBase::mutexQueueFinished,
    OptBase::mutexPOptimizers;

std::queue< std::pair<OptValue, OptBase*> >
    OptBase::queueTodo,
    OptBase::queueCalculated,
    OptBase::queueFinished;

std::vector<OptBase*>
    OptBase::pOptimizers;

OptBase::OptBase(const std::vector<OptBoundary> &optBoundaries,
                 unsigned int maxCalculations,
                 CalculatorBase* pCalculator,
                 OptTarget optTarget) :
    maxCalculations(maxCalculations),
    currentCalculation(0), ///@todo or start at 1?
    optBoundaries(optBoundaries),
    pCalculator(pCalculator),
    optTarget(optTarget),
    targetValue(0.0)
{
    mutexPOptimizers.lock();
    pOptimizers.push_back(this);
    mutexPOptimizers.unlock();
}

OptBase::~OptBase()
{

}

bool OptBase::optimise() ///@todo split this method into two [#1 only put new value onto to-calc queue ||| #2 save the result and move to next queue]
{
    OptValue newOptValue;

    if(currentCalculation >= maxCalculations) ///@todo might have to fix this condition
        return false;

    if(currentCalculation == 0) ///@todo care in case currentCalculation gets initalised with 1
    {
        bestCalculation.result = bad_value();
    }

    if(true) ///@todo currently this is always true, allow algorithms to stop somehow
    {
        newOptValue = get_next_value();
        ///@todo put new value in todo queue
    }
    return true;
}

void OptBase::add_finished_calculation(OptValue optValue, OptBase* pOptBase)
{
    mutexPreviousCalculations.lock();
    previousCalculations.push_back(optValue);
    mutexPreviousCalculations.unlock();
    mutexQueueFinished.lock();
    queueFinished.push({optValue, pOptBase});
    mutexQueueFinished.unlock();

    if(result_better(optValue, bestCalculation))
        bestCalculation = optValue;
}

T OptBase::bad_value() const
{
    switch(optTarget)
    {
        case MINIMIZE:
            return std::numeric_limits<T>::max();

        case MAXIMIZE:
            return std::numeric_limits<T>::min();

        case APPROACH:
            if(targetValue > 0.0)
                return std::numeric_limits<T>::min();
            else
                return std::numeric_limits<T>::max();

        case DIVERGE:
            return targetValue;

        default: //MINIMIZE
            return std::numeric_limits<T>::max();
    }
}

bool OptBase::result_better(const OptValue &result, const OptValue &other) const
{
    switch(optTarget)
    {
        case MINIMIZE:
            return result.result < other.result;

        case MAXIMIZE:
            return result.result > other.result;

        case APPROACH:
            return abs(targetValue - result.result) < abs(targetValue - other.result);

        case DIVERGE:
            return abs(targetValue - result.result) > abs(targetValue - other.result);

        default: //MINIMIZE
            return result.result < other.result;
    }
}

void OptBase::run_optimisations(unsigned int maxThreads)
{
    ///@todo

    //get the first to-calculate value of every optimizer
    //and push it onto the todo queue
    mutexPOptimizers.lock();
    for(const auto &pOptimizer : pOptimizers)
    {
        if(pOptimizer->previousCalculations.size() == 0)
            push_todo(pOptimizer->get_next_value(), pOptimizer);
    }
    mutexPOptimizers.unlock();

    ///@todo this is a non-threaded solution and should be fixed
    threaded_work();
}

T OptBase::random_factor()
{
    return rand()/(T)(RAND_MAX); ///@todo make sure this is properly seeded
}

void OptBase::threaded_work()
{
    while(true) ///@todo there has to be a check whether there still are calculations
    {
        if(available_todo())
        {
            ///@todo possible race condition here. Make it that pop checks for availability itself (return bool and have the value be a reference which is changed bool pop(out) )
            ///@todo or add another mutex which only locks for this check mutex availabilityCheck
            std::pair <OptValue, OptBase*> todo = pop_todo();
            OptValue optValue = todo.first;
            OptBase* pOptBase = todo.second;

            pOptBase->pCalculator->calculate(optValue);

            pOptBase->add_finished_calculation(optValue, pOptBase); ///@todo this method should be static (or not need the pointer argument)

            if(pOptBase->previousCalculations.size() > pOptBase->maxCalculations) ///@todo maybe be >=
                break;

            //only add the next one if there still are more
            push_todo(pOptBase->get_next_value(), pOptBase);

            ///@todo remove this method and the queue alltogether
            //push_calculated(optValue, pOptBase);

            ///@todo get rid of the calculated queue
            ///@todo and directly give the value back to the individual optimizer
            ///@todo and directly push it onto the finished queue then
            ///
        }

        std::this_thread::sleep_for(std::chrono::milliseconds(10)); ///@todo sleep time must be defineable by library user [maybe add as paramter to run_optimisations]
    }

}

void OptBase::push_todo(OptValue optValue, OptBase* pOptBase)
{
    mutexQueueTodo.lock();
    queueTodo.push({optValue, pOptBase});
    mutexQueueTodo.unlock();
}

void OptBase::push_calculated(OptValue optValue, OptBase *pOptBase)
{
    mutexQueueCalculated.lock();
    queueCalculated.push({optValue, pOptBase});
    mutexQueueCalculated.unlock();
}

void OptBase::push_finished(OptValue optValue, OptBase *pOptBase)
{
    mutexQueueFinished.lock();
    queueFinished.push({optValue, pOptBase});
    mutexQueueFinished.unlock();
}

bool OptBase::available_todo()
{
    bool out(false);

    mutexQueueTodo.lock();
    out = !queueTodo.empty();
    mutexQueueTodo.unlock();

    return out;
}

bool OptBase::available_calculated()
{
    bool out(false);

    mutexQueueCalculated.lock();
    out = !queueCalculated.empty();
    mutexQueueCalculated.unlock();

    return out;
}

bool OptBase::available_finished()
{
    bool out(false);

    mutexQueueFinished.lock();
    out = !queueFinished.empty();
    mutexQueueFinished.unlock();

    return out;
}

std::pair<OptValue, OptBase*> OptBase::pop_todo()
{
    mutexQueueTodo.lock();
    auto out = queueTodo.front();
    queueTodo.pop();
    mutexQueueTodo.unlock();
    return out;
}

std::pair<OptValue, OptBase*> OptBase::pop_calculated()
{
    mutexQueueCalculated.lock();
    auto out = queueCalculated.front();
    queueCalculated.pop();
    mutexQueueCalculated.unlock();
    return out;
}

std::pair<OptValue, OptBase*> OptBase::pop_finished()
{
    mutexQueueFinished.lock();
    auto out = queueFinished.front();
    queueFinished.pop();
    mutexQueueFinished.unlock();
    return out;
}

<|endoftext|>


<commit_before>#include "PhaseSolver.h"

#include <iostream.h>
#include <fstream.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#ifdef NEED_GETOPT
#include <getopt.h>
#endif /*NEED_GETOPT*/

// both of these are only needed for linking
Boolean checkTree = FALSE;
Boolean tracingEnabled = FALSE;

void
usage()
{
    cerr << "Usage: PmaxToMax -V lambda input-graph output-graph" << endl;
}

int
main(int argc, char** argv)
{
    double lambdaVal = 1.0;

    // parse arguments
    int ch;
    while ((ch = getopt(argc, argv, "V:")) != EOF) {
	switch (ch) {
	case 'V':
	    lambdaVal = atof(optarg);
	    break;

	default:
	    usage();
	    return 1;
	}
    }

    argc -= optind;
    //argv += optind;

    if (argc != 2) {
	usage();
	assert(0);
	return 1;
    }

    const char* instanceName = argv[optind];
    const char* outputName = argv[optind + 1];

    PhaseSolver* solver = new PhaseSolver();
    Boolean readOK =  solver->readDimacsInstance(instanceName);

    if (readOK == FALSE) {
	cout << "CANNOT READ INSTANCE" << endl;
	exit(-1);
	return 1;
    }

    cout << "read problem instance OK" << endl;

    ofstream dout(outputName, ios::out);
    if (dout == nil) {
	cerr << "Unable to open output file: " << outputName << endl;
	return 1;
    }

    time_t now = time(0);
    dout << "c" << endl;
    dout << "c  instance: " << instanceName << endl;
    dout << "c  convertedTime: " << ctime(&now);
    dout << "c  by PmaxToMax.C" << endl;
    dout << "c  lambda: " << lambdaVal << endl;

    dout << "c  argv: ";
    for (char** ap = argv; *ap != nil; ap++) {
	dout << *ap << " ";
    }
    dout << endl;

    solver->setInitialCapacity(lambdaVal);
    solver->writeInstance(dout);

    dout.close();

    return 0;
}
<commit_msg>Total re-write to be standalone program without using solver.<commit_after>#include "PhaseSolver.h"

#include <stdio.h>
#include <fstream.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
#ifdef NEED_GETOPT
#include <getopt.h>
#endif /*NEED_GETOPT*/

// both of these are only needed for linking
Boolean checkTree = FALSE;
Boolean tracingEnabled = FALSE;

void
usage()
{
    cerr << "Usage: PmaxToMax -V lambda input-graph output-graph" << endl;
}

int
main(int argc, char** argv)
{
    double lambdaVal = 1.0;

    // parse arguments
    int ch;
    while ((ch = getopt(argc, argv, "V:")) != EOF) {
	switch (ch) {
	case 'V':
	    lambdaVal = atof(optarg);
	    break;

	default:
	    usage();
	    return 1;
	}
    }

    argc -= optind;
    //argv += optind;

    if (argc != 2) {
	usage();
	assert(0);
	return 1;
    }

    const char* instanceName = argv[optind];
    const char* outputName = argv[optind + 1];

    FILE* in = fopen(instanceName, "r");
    if (in == NULL) {
	perror("Cannot open input instance.");
	exit(1);
    }
    FILE* out = fopen(outputName, "w");
    if (out == NULL) {
	perror("Cannot open output instance.");
	exit(1);
    }
    fprintf(out, "c  converted from %s with lambda=%f\n", instanceName, lambdaVal);

    char line[1024];
    int sourceId = -1;
    int sinkId = -1;

    for (;;) {
	char* str = fgets(line, 1024, in);
	if (str == NULL) {
	    break;
	}

	int ch = *str;
	char c1, c2;
	int id, head, tail, aParam;
	int ntoks;
	double bParam;

	switch(ch) {
	case 'a':
	    ntoks = sscanf(line, "%c %d %d %d %lf", &c1, &tail, &head, &aParam, &bParam);
	    if (ntoks == 5) {
		int cap = aParam;
		// parametric line
		if (bParam != 0) {
		    cap = (int)(aParam + bParam * lambdaVal);
		    if (head == sinkId) {
			if (bParam > 0) {
			    // it's a mining arc
			    if (cap < 0) {
				// leave it at the sink - but negate the cap
				cap = -cap;
			    } else {
				// move it to the source
				head = tail;
				tail = sourceId;
			    }
			} else {
			    // "normal" graph
			    if (cap < 0) {
				// move it to source with postive cap
				head = tail;
				tail = sourceId;
				cap = -cap;
			    }
			}
		    } else if (tail == sourceId) {
			// source-arc, b is always > 0
			if (cap < 0) {
			    // move it to the sink
			    tail = head;
			    head = sinkId;
			    cap = -cap;
			}
		    }
		}  else {
		    // have a zero b value
		    if ((head == sinkId) && (cap < 0)) {
			// mining block
			cap = -cap;
		    }
		}
		assert(cap >= 0);
		fprintf(out, "a %d %d %d\n", tail, head, cap);
		continue;
	    }
	    break;
	case 'n':
	    sscanf(line, "%c %d %c", &c1, &id, &c2);
	    if (c2 == 's') {
		sourceId = id;
	    } else if (c2 == 't') {
		sinkId = id;
	    }
	    break;
	}

	// just copy the line to the output
	fprintf(out, line);
    }

    fclose(out);

    return 0;
}
<|endoftext|>


<commit_before>#include "Manager.h"

#include <QDebug>
#include <QMenu>
#include <QApplication>
#include <QDesktopWidget>
#include <QScreen>
#include <QDesktopWidget>
#include <QThread>
#include <QSettings>
#include <QClipboard>
#include <QMessageBox>
#include <QInputDialog>
#include <QNetworkProxy>

#include "Settings.h"
#include "SettingsEditor.h"
#include "SelectionDialog.h"
#include "GlobalActionHelper.h"
#include "Recognizer.h"
#include "WebTranslator.h"
#include "ResultDialog.h"
#include "LanguageHelper.h"
#include "StAssert.h"
#include "Utils.h"

Manager::Manager (QObject *parent) :
  QObject (parent),
  trayIcon_ (new QSystemTrayIcon (this)),
  dictionary_ (new LanguageHelper),
  resultDialog_ (new ResultDialog (*dictionary_)),
  captureAction_ (NULL), repeatCaptureAction_ (NULL),
  repeatAction_ (NULL), clipboardAction_ (NULL),
  useResultDialog_ (true), doTranslation_ (true), itemProcessingCount_ (0) {
  updateNormalIcon ();
  GlobalActionHelper::init ();
  qRegisterMetaType<ProcessingItem>();

  // Recognizer
  Recognizer *recognizer = new Recognizer;
  connect (this, SIGNAL (requestRecognize (ProcessingItem)),
           recognizer, SLOT (recognize (ProcessingItem)));
  connect (recognizer, SIGNAL (recognized (ProcessingItem)),
           this, SIGNAL (requestTranslate (ProcessingItem)));
  connect (recognizer, SIGNAL (error (QString)),
           SLOT (showError (QString)));
  connect (this, SIGNAL (settingsEdited ()),
           recognizer, SLOT (applySettings ()));
  QThread *recognizerThread = new QThread (this);
  threads_ << recognizerThread;
  recognizer->moveToThread (recognizerThread);
  recognizerThread->start ();
  connect (qApp, SIGNAL (aboutToQuit ()), recognizerThread, SLOT (quit ()));

  // Translator
  WebTranslator *translator = new WebTranslator;
  connect (this, SIGNAL (requestTranslate (ProcessingItem)),
           translator, SLOT (translate (ProcessingItem)));
  connect (translator, SIGNAL (translated (ProcessingItem)),
           SLOT (showResult (ProcessingItem)));
  connect (translator, SIGNAL (error (QString)),
           SLOT (showError (QString)));
  connect (this, SIGNAL (settingsEdited ()),
           translator, SLOT (applySettings ()));

  connect (this, SIGNAL (settingsEdited ()), this, SLOT (applySettings ()));

  resultDialog_->setWindowIcon (trayIcon_->icon ());
  connect (this, SIGNAL (settingsEdited ()), resultDialog_, SLOT (applySettings ()));
  connect (resultDialog_, SIGNAL (requestRecognize (ProcessingItem)),
           this, SIGNAL (requestRecognize (ProcessingItem)));
  connect (resultDialog_, SIGNAL (requestTranslate (ProcessingItem)),
           this, SIGNAL (requestTranslate (ProcessingItem)));
  connect (resultDialog_, SIGNAL (requestClipboard ()), SLOT (copyLastToClipboard ()));
  connect (resultDialog_, SIGNAL (requestImageClipboard ()),
           SLOT (copyLastImageToClipboard ()));
  connect (resultDialog_, SIGNAL (requestEdition (ProcessingItem)),
           this, SLOT (editRecognized (ProcessingItem)));

  connect (trayIcon_, SIGNAL (activated (QSystemTrayIcon::ActivationReason)),
           SLOT (processTrayAction (QSystemTrayIcon::ActivationReason)));

  trayIcon_->setContextMenu (trayContextMenu ());
  updateActionsState ();
  trayIcon_->show ();

  applySettings ();
}

QMenu * Manager::trayContextMenu () {
  QMenu *menu = new QMenu ();
  captureAction_ = menu->addAction (tr ("Захват"), this, SLOT (capture ()));
  repeatCaptureAction_ = menu->addAction (tr ("Повторить захват"),
                                          this, SLOT (repeatCapture ()));
  QMenu *translateMenu = menu->addMenu (tr ("Результат"));
  repeatAction_ = translateMenu->addAction (tr ("Показать"), this,
                                            SLOT (showLast ()));
  clipboardAction_ = translateMenu->addAction (tr ("В буфер"), this,
                                               SLOT (copyLastToClipboard ()));
  menu->addAction (tr ("Настройки"), this, SLOT (settings ()));
  menu->addAction (tr ("О программе"), this, SLOT (about ()));
  menu->addAction (tr ("Выход"), this, SLOT (close ()));
  return menu;
}

void Manager::updateActionsState (bool isEnabled) {
#ifdef Q_OS_LINUX
  // Avoid unneeded tray blinking (required to update context menu).
  QList<QAction *> actions;
  actions << captureAction_ << repeatCaptureAction_ << repeatAction_ << clipboardAction_;
  QList<bool> states;
  foreach (const QAction * action, actions) {
    states << action->isEnabled ();
  }
#endif
  captureAction_->setEnabled (isEnabled);
  repeatCaptureAction_->setEnabled (isEnabled && !selections_.isEmpty ());
  const ProcessingItem &lastItem = resultDialog_->item ();
  repeatAction_->setEnabled (isEnabled && lastItem.isValid ());
  clipboardAction_->setEnabled (isEnabled && lastItem.isValid ());
#ifdef Q_OS_LINUX
  for (int i = 0, end = actions.size (); i < end; ++i) {
    if (states.at (i) != actions.at (i)->isEnabled ()) {
      trayIcon_->hide ();
      trayIcon_->show ();
      break;
    }
  }
#endif
}

void Manager::applySettings () {
#define GET(NAME) settings.value (settings_names::NAME, settings_values::NAME)
  QSettings settings;
  settings.beginGroup (settings_names::guiGroup);

  Q_CHECK_PTR (captureAction_);
  GlobalActionHelper::removeGlobal (captureAction_);
  captureAction_->setShortcut (GET (captureHotkey).toString ());
  GlobalActionHelper::makeGlobal (captureAction_);

  Q_CHECK_PTR (repeatCaptureAction_);
  GlobalActionHelper::removeGlobal (repeatCaptureAction_);
  repeatCaptureAction_->setShortcut (GET (repeatCaptureHotkey).toString ());
  GlobalActionHelper::makeGlobal (repeatCaptureAction_);

  Q_CHECK_PTR (repeatAction_);
  GlobalActionHelper::removeGlobal (repeatAction_);
  repeatAction_->setShortcut (GET (repeatHotkey).toString ());
  GlobalActionHelper::makeGlobal (repeatAction_);

  Q_CHECK_PTR (clipboardAction_);
  GlobalActionHelper::removeGlobal (clipboardAction_);
  clipboardAction_->setShortcut (GET (clipboardHotkey).toString ());
  GlobalActionHelper::makeGlobal (clipboardAction_);

  // Depends on SettingsEditor button indexes. 1==dialog
  useResultDialog_ = GET (resultShowType).toBool ();

  QNetworkProxy proxy = QNetworkProxy::applicationProxy ();
  QList<int> proxyTypes = proxyTypeOrder ();
  int proxyTypeIndex = std::min (GET (proxyType).toInt (), proxyTypes.size ());
  proxy.setType (QNetworkProxy::ProxyType (proxyTypes.at (std::max (proxyTypeIndex, 0))));
  proxy.setHostName (GET (proxyHostName).toString ());
  proxy.setPort (GET (proxyPort).toInt ());
  proxy.setUser (GET (proxyUser).toString ());
  if (GET (proxySavePassword).toBool ()) {
    proxy.setPassword (encode (GET (proxyPassword).toString ()));
  }
  QNetworkProxy::setApplicationProxy (proxy);
  settings.endGroup ();

  settings.beginGroup (settings_names::recogntionGroup);
  defaultOrcLanguage_ = GET (ocrLanguage).toString ();
  settings.endGroup ();

  settings.beginGroup (settings_names::translationGroup);
  defaultTranslationLanguage_ = GET (translationLanguage).toString ();
  doTranslation_ = GET (doTranslation).toBool ();
  settings.endGroup ();

  Q_CHECK_PTR (dictionary_);
  dictionary_->updateAvailableOcrLanguages ();
#undef GET
}

Manager::~Manager () {
  foreach (SelectionDialog * selection, selections_.values ()) {
    selection->hide ();
    delete selection;
  }
  trayIcon_->hide ();
  delete trayIcon_->contextMenu ();
  foreach (QThread * thread, threads_) {
    thread->quit ();
    thread->wait (1000000);
  }
}

void Manager::capture () {
  QList<QScreen *> screens = QApplication::screens ();
  foreach (QScreen * screen, screens) {
    QRect geometry = screen->availableGeometry ();
    QPixmap pixmap = screen->grabWindow (0, geometry.x (), geometry.y (),
                                         geometry.width (), geometry.height ());
    QString name = screen->name ();
    if (!selections_.contains (name)) {
      SelectionDialog *selection = new SelectionDialog (*dictionary_);
      selection->setWindowIcon (trayIcon_->icon ());
      connect (this, SIGNAL (closeSelections ()), selection, SLOT (close ()));
      connect (this, SIGNAL (settingsEdited ()), selection, SLOT (applySettings ()));
      connect (selection, SIGNAL (selected (ProcessingItem)),
               SLOT (handleSelection (ProcessingItem)));
      connect (selection, SIGNAL (rejected ()), SIGNAL (closeSelections ()));
      selections_[name] = selection;
    }
    SelectionDialog *selection = selections_[name];
    selection->setPixmap (pixmap, geometry);
  }
  updateActionsState ();
}

void Manager::handleSelection (ProcessingItem item) {
  bool altMod = item.modifiers & Qt::AltModifier;
  bool doTranslation = (doTranslation_ && !altMod) || (!doTranslation_ && altMod);
  if (doTranslation) {
    item.translateLanguage = defaultTranslationLanguage_;
  }
  if (item.ocrLanguage.isEmpty ()) {
    item.ocrLanguage = defaultOrcLanguage_;
  }
  if (item.swapLanguages_) {
    QString translate = (item.translateLanguage.isEmpty ())
                        ? defaultTranslationLanguage_ : item.translateLanguage;
    if (doTranslation) {
      item.translateLanguage = dictionary_->ocrToTranslateCodes (item.ocrLanguage);
    }
    item.sourceLanguage.clear ();
    item.ocrLanguage = dictionary_->translateToOcrCodes (translate);
    if (item.ocrLanguage.isEmpty ()) {
      showError (tr ("Не найден подходящий язык распознавания."));
      return;
    }
  }
  if (item.sourceLanguage.isEmpty ()) {
    item.sourceLanguage = dictionary_->ocrToTranslateCodes (item.ocrLanguage);
  }
  emit requestRecognize (item);
  ++itemProcessingCount_;
  updateNormalIcon ();
  if (!(item.modifiers & Qt::ControlModifier)) {
    emit closeSelections ();
  }
}

void Manager::repeatCapture () {
  if (selections_.isEmpty ()) {
    return;
  }
  QList<QScreen *> screens = QApplication::screens ();
  foreach (QScreen * screen, screens) {
    QString name = screen->name ();
    if (!selections_.contains (name)) {
      continue;
    }
    SelectionDialog *selection = selections_[name];
    selection->show ();
    selection->activateWindow ();
  }
}

void Manager::settings () {
  SettingsEditor editor (*dictionary_);
  editor.setWindowIcon (trayIcon_->icon ());
  connect (&editor, SIGNAL (settingsEdited ()), SIGNAL (settingsEdited ()));
  updateActionsState (false);
  editor.exec ();
  updateActionsState (true);
}

void Manager::close () {
  QApplication::quit ();
}

void Manager::about () {
  QString version = "2.0.0";
  QString text = tr ("Программа для распознавания текста на экране.\n" \
                     "Создана с использованием Qt, tesseract-ocr, Google Translate.\n"
                     "Автор: Gres (translator@gres.biz)\n"
                     "Версия: %1 от %2 %3").arg (version)
                 .arg (__DATE__).arg (__TIME__);
  QString tips = tr ("\n\nПодсказки.\n"
                     "Клик по иконке в трее:\n"
                     "* левой кнопкой - отобразить последний результат\n"
                     "* средней кнопкой - скопировать последний результат в буфер обмена\n"
#ifdef Q_OS_WIN
                     "* двойной клик - повторный захват последнего экрана\n"
#endif
                     "\n"
                     "Захвата изображения при зажатых кнопках:\n"
                     "* Ctrl - не выходить из режима захвата\n"
                     "* Alt - выполнить перевод, если в настройках он выключен "
                     "(и наоборот, не выполнять, если включен)\n"
                     "");

  QMessageBox message (QMessageBox::Information, tr ("О программе"), text + tips,
                       QMessageBox::Ok);
  message.setIconPixmap (trayIcon_->icon ().pixmap (QSize (64, 64)));
  message.exec ();
}

void Manager::processTrayAction (QSystemTrayIcon::ActivationReason reason) {
  if (reason == QSystemTrayIcon::Trigger && repeatAction_->isEnabled ()) {
    showLast ();
  }
  else if (reason == QSystemTrayIcon::MiddleClick && clipboardAction_->isEnabled ()) {
    copyLastToClipboard  ();
    trayIcon_->showMessage (tr ("Результат"),
                            tr ("Последний результат был скопирован в буфер обмена."),
                            QSystemTrayIcon::Information);
  }
  else if (reason == QSystemTrayIcon::DoubleClick && repeatCaptureAction_->isEnabled ()) {
    repeatCapture ();
  }
}

void Manager::editRecognized (ProcessingItem item) {
  QString fixed = QInputDialog::getMultiLineText (
    NULL, tr ("Правка"), tr ("Исправьте распознанный текст"), item.recognized);
  if (!fixed.isEmpty ()) {
    item.recognized = fixed;
    emit requestTranslate (item);
  }
}

void Manager::showLast () {
  const ProcessingItem &item = resultDialog_->item ();
  if (item.isValid ()) {
    showResult (item);
  }
}

void Manager::copyLastToClipboard () {
  const ProcessingItem &item = resultDialog_->item ();
  if (item.isValid ()) {
    QClipboard *clipboard = QApplication::clipboard ();
    QString message = item.recognized;
    if (!item.translated.isEmpty ()) {
      message += " - " + item.translated;
    }
    clipboard->setText (message);
  }
}

void Manager::copyLastImageToClipboard () {
  const ProcessingItem &item = resultDialog_->item ();
  if (item.isValid ()) {
    QClipboard *clipboard = QApplication::clipboard ();
    clipboard->setPixmap (item.source);
  }
}

void Manager::showResult (ProcessingItem item) {
  --itemProcessingCount_;
  if (!item.isValid ()) {
    // delay because it can show error
    QTimer::singleShot (3000, this, SLOT (updateNormalIcon ()));
    return;
  }
  changeIcon (IconTypeSuccess);
  if (useResultDialog_) {
    resultDialog_->showResult (item);
  }
  else {
    QString message = item.recognized + " - " + item.translated;
    trayIcon_->showMessage (tr ("Результат"), message, QSystemTrayIcon::Information);
  }
  updateActionsState ();
}

void Manager::showError (QString text) {
  qCritical () << text;
  changeIcon (IconTypeError);
  trayIcon_->showMessage (tr ("Ошибка"), text, QSystemTrayIcon::Critical);
}

void Manager::changeIcon (int iconType, int timeoutMsec) {
  QString fileName;
  switch (iconType) {
    case IconTypeSuccess:
      fileName = ":/images/STIconGreen.png";
      break;
    case IconTypeError:
      fileName = ":/images/STIconRed.png";
      break;
    default:
      return;
  }
  trayIcon_->setIcon (QIcon (fileName));
  if (timeoutMsec > 0) {
    QTimer::singleShot (timeoutMsec, this, SLOT (updateNormalIcon ()));
  }
}

void Manager::updateNormalIcon () {
  QString fileName = itemProcessingCount_ > 0
                     ? ":/images/STIconOrange.png" : ":/images/STIconBlue.png";
  trayIcon_->setIcon (QIcon (fileName));
}
<commit_msg>Fixed icon change to processing after last item show.<commit_after>#include "Manager.h"

#include <QDebug>
#include <QMenu>
#include <QApplication>
#include <QDesktopWidget>
#include <QScreen>
#include <QDesktopWidget>
#include <QThread>
#include <QSettings>
#include <QClipboard>
#include <QMessageBox>
#include <QInputDialog>
#include <QNetworkProxy>

#include "Settings.h"
#include "SettingsEditor.h"
#include "SelectionDialog.h"
#include "GlobalActionHelper.h"
#include "Recognizer.h"
#include "WebTranslator.h"
#include "ResultDialog.h"
#include "LanguageHelper.h"
#include "StAssert.h"
#include "Utils.h"

Manager::Manager (QObject *parent) :
  QObject (parent),
  trayIcon_ (new QSystemTrayIcon (this)),
  dictionary_ (new LanguageHelper),
  resultDialog_ (new ResultDialog (*dictionary_)),
  captureAction_ (NULL), repeatCaptureAction_ (NULL),
  repeatAction_ (NULL), clipboardAction_ (NULL),
  useResultDialog_ (true), doTranslation_ (true), itemProcessingCount_ (0) {
  updateNormalIcon ();
  GlobalActionHelper::init ();
  qRegisterMetaType<ProcessingItem>();

  // Recognizer
  Recognizer *recognizer = new Recognizer;
  connect (this, SIGNAL (requestRecognize (ProcessingItem)),
           recognizer, SLOT (recognize (ProcessingItem)));
  connect (recognizer, SIGNAL (recognized (ProcessingItem)),
           this, SIGNAL (requestTranslate (ProcessingItem)));
  connect (recognizer, SIGNAL (error (QString)),
           SLOT (showError (QString)));
  connect (this, SIGNAL (settingsEdited ()),
           recognizer, SLOT (applySettings ()));
  QThread *recognizerThread = new QThread (this);
  threads_ << recognizerThread;
  recognizer->moveToThread (recognizerThread);
  recognizerThread->start ();
  connect (qApp, SIGNAL (aboutToQuit ()), recognizerThread, SLOT (quit ()));

  // Translator
  WebTranslator *translator = new WebTranslator;
  connect (this, SIGNAL (requestTranslate (ProcessingItem)),
           translator, SLOT (translate (ProcessingItem)));
  connect (translator, SIGNAL (translated (ProcessingItem)),
           SLOT (showResult (ProcessingItem)));
  connect (translator, SIGNAL (error (QString)),
           SLOT (showError (QString)));
  connect (this, SIGNAL (settingsEdited ()),
           translator, SLOT (applySettings ()));

  connect (this, SIGNAL (settingsEdited ()), this, SLOT (applySettings ()));

  resultDialog_->setWindowIcon (trayIcon_->icon ());
  connect (this, SIGNAL (settingsEdited ()), resultDialog_, SLOT (applySettings ()));
  connect (resultDialog_, SIGNAL (requestRecognize (ProcessingItem)),
           this, SIGNAL (requestRecognize (ProcessingItem)));
  connect (resultDialog_, SIGNAL (requestTranslate (ProcessingItem)),
           this, SIGNAL (requestTranslate (ProcessingItem)));
  connect (resultDialog_, SIGNAL (requestClipboard ()), SLOT (copyLastToClipboard ()));
  connect (resultDialog_, SIGNAL (requestImageClipboard ()),
           SLOT (copyLastImageToClipboard ()));
  connect (resultDialog_, SIGNAL (requestEdition (ProcessingItem)),
           this, SLOT (editRecognized (ProcessingItem)));

  connect (trayIcon_, SIGNAL (activated (QSystemTrayIcon::ActivationReason)),
           SLOT (processTrayAction (QSystemTrayIcon::ActivationReason)));

  trayIcon_->setContextMenu (trayContextMenu ());
  updateActionsState ();
  trayIcon_->show ();

  applySettings ();
}

QMenu * Manager::trayContextMenu () {
  QMenu *menu = new QMenu ();
  captureAction_ = menu->addAction (tr ("Захват"), this, SLOT (capture ()));
  repeatCaptureAction_ = menu->addAction (tr ("Повторить захват"),
                                          this, SLOT (repeatCapture ()));
  QMenu *translateMenu = menu->addMenu (tr ("Результат"));
  repeatAction_ = translateMenu->addAction (tr ("Показать"), this,
                                            SLOT (showLast ()));
  clipboardAction_ = translateMenu->addAction (tr ("В буфер"), this,
                                               SLOT (copyLastToClipboard ()));
  menu->addAction (tr ("Настройки"), this, SLOT (settings ()));
  menu->addAction (tr ("О программе"), this, SLOT (about ()));
  menu->addAction (tr ("Выход"), this, SLOT (close ()));
  return menu;
}

void Manager::updateActionsState (bool isEnabled) {
#ifdef Q_OS_LINUX
  // Avoid unneeded tray blinking (required to update context menu).
  QList<QAction *> actions;
  actions << captureAction_ << repeatCaptureAction_ << repeatAction_ << clipboardAction_;
  QList<bool> states;
  foreach (const QAction * action, actions) {
    states << action->isEnabled ();
  }
#endif
  captureAction_->setEnabled (isEnabled);
  repeatCaptureAction_->setEnabled (isEnabled && !selections_.isEmpty ());
  const ProcessingItem &lastItem = resultDialog_->item ();
  repeatAction_->setEnabled (isEnabled && lastItem.isValid ());
  clipboardAction_->setEnabled (isEnabled && lastItem.isValid ());
#ifdef Q_OS_LINUX
  for (int i = 0, end = actions.size (); i < end; ++i) {
    if (states.at (i) != actions.at (i)->isEnabled ()) {
      trayIcon_->hide ();
      trayIcon_->show ();
      break;
    }
  }
#endif
}

void Manager::applySettings () {
#define GET(NAME) settings.value (settings_names::NAME, settings_values::NAME)
  QSettings settings;
  settings.beginGroup (settings_names::guiGroup);

  Q_CHECK_PTR (captureAction_);
  GlobalActionHelper::removeGlobal (captureAction_);
  captureAction_->setShortcut (GET (captureHotkey).toString ());
  GlobalActionHelper::makeGlobal (captureAction_);

  Q_CHECK_PTR (repeatCaptureAction_);
  GlobalActionHelper::removeGlobal (repeatCaptureAction_);
  repeatCaptureAction_->setShortcut (GET (repeatCaptureHotkey).toString ());
  GlobalActionHelper::makeGlobal (repeatCaptureAction_);

  Q_CHECK_PTR (repeatAction_);
  GlobalActionHelper::removeGlobal (repeatAction_);
  repeatAction_->setShortcut (GET (repeatHotkey).toString ());
  GlobalActionHelper::makeGlobal (repeatAction_);

  Q_CHECK_PTR (clipboardAction_);
  GlobalActionHelper::removeGlobal (clipboardAction_);
  clipboardAction_->setShortcut (GET (clipboardHotkey).toString ());
  GlobalActionHelper::makeGlobal (clipboardAction_);

  // Depends on SettingsEditor button indexes. 1==dialog
  useResultDialog_ = GET (resultShowType).toBool ();

  QNetworkProxy proxy = QNetworkProxy::applicationProxy ();
  QList<int> proxyTypes = proxyTypeOrder ();
  int proxyTypeIndex = std::min (GET (proxyType).toInt (), proxyTypes.size ());
  proxy.setType (QNetworkProxy::ProxyType (proxyTypes.at (std::max (proxyTypeIndex, 0))));
  proxy.setHostName (GET (proxyHostName).toString ());
  proxy.setPort (GET (proxyPort).toInt ());
  proxy.setUser (GET (proxyUser).toString ());
  if (GET (proxySavePassword).toBool ()) {
    proxy.setPassword (encode (GET (proxyPassword).toString ()));
  }
  QNetworkProxy::setApplicationProxy (proxy);
  settings.endGroup ();

  settings.beginGroup (settings_names::recogntionGroup);
  defaultOrcLanguage_ = GET (ocrLanguage).toString ();
  settings.endGroup ();

  settings.beginGroup (settings_names::translationGroup);
  defaultTranslationLanguage_ = GET (translationLanguage).toString ();
  doTranslation_ = GET (doTranslation).toBool ();
  settings.endGroup ();

  Q_CHECK_PTR (dictionary_);
  dictionary_->updateAvailableOcrLanguages ();
#undef GET
}

Manager::~Manager () {
  foreach (SelectionDialog * selection, selections_.values ()) {
    selection->hide ();
    delete selection;
  }
  trayIcon_->hide ();
  delete trayIcon_->contextMenu ();
  foreach (QThread * thread, threads_) {
    thread->quit ();
    thread->wait (1000000);
  }
}

void Manager::capture () {
  QList<QScreen *> screens = QApplication::screens ();
  foreach (QScreen * screen, screens) {
    QRect geometry = screen->availableGeometry ();
    QPixmap pixmap = screen->grabWindow (0, geometry.x (), geometry.y (),
                                         geometry.width (), geometry.height ());
    QString name = screen->name ();
    if (!selections_.contains (name)) {
      SelectionDialog *selection = new SelectionDialog (*dictionary_);
      selection->setWindowIcon (trayIcon_->icon ());
      connect (this, SIGNAL (closeSelections ()), selection, SLOT (close ()));
      connect (this, SIGNAL (settingsEdited ()), selection, SLOT (applySettings ()));
      connect (selection, SIGNAL (selected (ProcessingItem)),
               SLOT (handleSelection (ProcessingItem)));
      connect (selection, SIGNAL (rejected ()), SIGNAL (closeSelections ()));
      selections_[name] = selection;
    }
    SelectionDialog *selection = selections_[name];
    selection->setPixmap (pixmap, geometry);
  }
  updateActionsState ();
}

void Manager::handleSelection (ProcessingItem item) {
  bool altMod = item.modifiers & Qt::AltModifier;
  bool doTranslation = (doTranslation_ && !altMod) || (!doTranslation_ && altMod);
  if (doTranslation) {
    item.translateLanguage = defaultTranslationLanguage_;
  }
  if (item.ocrLanguage.isEmpty ()) {
    item.ocrLanguage = defaultOrcLanguage_;
  }
  if (item.swapLanguages_) {
    QString translate = (item.translateLanguage.isEmpty ())
                        ? defaultTranslationLanguage_ : item.translateLanguage;
    if (doTranslation) {
      item.translateLanguage = dictionary_->ocrToTranslateCodes (item.ocrLanguage);
    }
    item.sourceLanguage.clear ();
    item.ocrLanguage = dictionary_->translateToOcrCodes (translate);
    if (item.ocrLanguage.isEmpty ()) {
      showError (tr ("Не найден подходящий язык распознавания."));
      return;
    }
  }
  if (item.sourceLanguage.isEmpty ()) {
    item.sourceLanguage = dictionary_->ocrToTranslateCodes (item.ocrLanguage);
  }
  emit requestRecognize (item);
  ++itemProcessingCount_;
  updateNormalIcon ();
  if (!(item.modifiers & Qt::ControlModifier)) {
    emit closeSelections ();
  }
}

void Manager::repeatCapture () {
  if (selections_.isEmpty ()) {
    return;
  }
  QList<QScreen *> screens = QApplication::screens ();
  foreach (QScreen * screen, screens) {
    QString name = screen->name ();
    if (!selections_.contains (name)) {
      continue;
    }
    SelectionDialog *selection = selections_[name];
    selection->show ();
    selection->activateWindow ();
  }
}

void Manager::settings () {
  SettingsEditor editor (*dictionary_);
  editor.setWindowIcon (trayIcon_->icon ());
  connect (&editor, SIGNAL (settingsEdited ()), SIGNAL (settingsEdited ()));
  updateActionsState (false);
  editor.exec ();
  updateActionsState (true);
}

void Manager::close () {
  QApplication::quit ();
}

void Manager::about () {
  QString version = "2.0.0";
  QString text = tr ("Программа для распознавания текста на экране.\n" \
                     "Создана с использованием Qt, tesseract-ocr, Google Translate.\n"
                     "Автор: Gres (translator@gres.biz)\n"
                     "Версия: %1 от %2 %3").arg (version)
                 .arg (__DATE__).arg (__TIME__);
  QString tips = tr ("\n\nПодсказки.\n"
                     "Клик по иконке в трее:\n"
                     "* левой кнопкой - отобразить последний результат\n"
                     "* средней кнопкой - скопировать последний результат в буфер обмена\n"
#ifdef Q_OS_WIN
                     "* двойной клик - повторный захват последнего экрана\n"
#endif
                     "\n"
                     "Захвата изображения при зажатых кнопках:\n"
                     "* Ctrl - не выходить из режима захвата\n"
                     "* Alt - выполнить перевод, если в настройках он выключен "
                     "(и наоборот, не выполнять, если включен)\n"
                     "");

  QMessageBox message (QMessageBox::Information, tr ("О программе"), text + tips,
                       QMessageBox::Ok);
  message.setIconPixmap (trayIcon_->icon ().pixmap (QSize (64, 64)));
  message.exec ();
}

void Manager::processTrayAction (QSystemTrayIcon::ActivationReason reason) {
  if (reason == QSystemTrayIcon::Trigger && repeatAction_->isEnabled ()) {
    showLast ();
  }
  else if (reason == QSystemTrayIcon::MiddleClick && clipboardAction_->isEnabled ()) {
    copyLastToClipboard  ();
    trayIcon_->showMessage (tr ("Результат"),
                            tr ("Последний результат был скопирован в буфер обмена."),
                            QSystemTrayIcon::Information);
  }
  else if (reason == QSystemTrayIcon::DoubleClick && repeatCaptureAction_->isEnabled ()) {
    repeatCapture ();
  }
}

void Manager::editRecognized (ProcessingItem item) {
  QString fixed = QInputDialog::getMultiLineText (
    NULL, tr ("Правка"), tr ("Исправьте распознанный текст"), item.recognized);
  if (!fixed.isEmpty ()) {
    item.recognized = fixed;
    emit requestTranslate (item);
  }
}

void Manager::showLast () {
  const ProcessingItem &item = resultDialog_->item ();
  if (item.isValid ()) {
    ++itemProcessingCount_;
    showResult (item);
  }
}

void Manager::copyLastToClipboard () {
  const ProcessingItem &item = resultDialog_->item ();
  if (item.isValid ()) {
    QClipboard *clipboard = QApplication::clipboard ();
    QString message = item.recognized;
    if (!item.translated.isEmpty ()) {
      message += " - " + item.translated;
    }
    clipboard->setText (message);
  }
}

void Manager::copyLastImageToClipboard () {
  const ProcessingItem &item = resultDialog_->item ();
  if (item.isValid ()) {
    QClipboard *clipboard = QApplication::clipboard ();
    clipboard->setPixmap (item.source);
  }
}

void Manager::showResult (ProcessingItem item) {
  --itemProcessingCount_;
  if (!item.isValid ()) {
    // delay because it can show error
    QTimer::singleShot (3000, this, SLOT (updateNormalIcon ()));
    return;
  }
  changeIcon (IconTypeSuccess);
  if (useResultDialog_) {
    resultDialog_->showResult (item);
  }
  else {
    QString message = item.recognized + " - " + item.translated;
    trayIcon_->showMessage (tr ("Результат"), message, QSystemTrayIcon::Information);
  }
  updateActionsState ();
}

void Manager::showError (QString text) {
  qCritical () << text;
  changeIcon (IconTypeError);
  trayIcon_->showMessage (tr ("Ошибка"), text, QSystemTrayIcon::Critical);
}

void Manager::changeIcon (int iconType, int timeoutMsec) {
  QString fileName;
  switch (iconType) {
    case IconTypeSuccess:
      fileName = ":/images/STIconGreen.png";
      break;
    case IconTypeError:
      fileName = ":/images/STIconRed.png";
      break;
    default:
      return;
  }
  trayIcon_->setIcon (QIcon (fileName));
  if (timeoutMsec > 0) {
    QTimer::singleShot (timeoutMsec, this, SLOT (updateNormalIcon ()));
  }
}

void Manager::updateNormalIcon () {
  QString fileName = itemProcessingCount_ > 0
                     ? ":/images/STIconOrange.png" : ":/images/STIconBlue.png";
  trayIcon_->setIcon (QIcon (fileName));
}
<|endoftext|>


<commit_before>// NCModule.cc

// This file is part of bes, A C++ back-end server implementation framework
// for the OPeNDAP Data Access Protocol.

// Copyright (c) 2004,2005 University Corporation for Atmospheric Research
// Author: Patrick West <pwest@ucar.org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can contact University Corporation for Atmospheric Research at
// 3080 Center Green Drive, Boulder, CO 80301

// (c) COPYRIGHT University Corporation for Atmostpheric Research 2004-2005
// Please read the full copyright statement in the file COPYRIGHT_UCAR.
//
// Authors:
//      pwest       Patrick West <pwest@ucar.edu>

#include <iostream>

using std::endl ;

#include "NCModule.h"
#include "BESRequestHandlerList.h"
#include "NCRequestHandler.h"
#include "BESContainerStorageList.h"
#include "BESContainerStorageCatalog.h"
#include "BESCatalogDirectory.h"
#include "BESCatalogList.h"
#include "BESLog.h"

#define NC_CATALOG "catalog"

void
NCModule::initialize( const string &modname )
{
    if( BESLog::TheLog()->is_verbose() )
	(*BESLog::TheLog()) << "Initializing NC:" << endl ;

    if( BESLog::TheLog()->is_verbose() )
	(*BESLog::TheLog()) << "    adding " << modname << " request handler"
		      << endl ;
    BESRequestHandlerList::TheList()->add_handler( modname, new NCRequestHandler( modname ) ) ;

    if( BESLog::TheLog()->is_verbose() )
	(*BESLog::TheLog()) << "    adding " << NC_CATALOG << " catalog"
		      << endl ;
    BESCatalogList::TheCatalogList()->add_catalog( new BESCatalogDirectory( NC_CATALOG ) ) ;

    if( BESLog::TheLog()->is_verbose() )
	(*BESLog::TheLog()) << "Adding Catalog Container Storage" << endl;
    BESContainerStorageCatalog *csc = new BESContainerStorageCatalog( NC_CATALOG ) ;
    BESContainerStorageList::TheList()->add_persistence( csc ) ;
}

void
NCModule::terminate( const string &modname )
{
    if( BESLog::TheLog()->is_verbose() )
	(*BESLog::TheLog()) << "Removing NC Handlers" << endl;
    BESRequestHandler *rh = BESRequestHandlerList::TheList()->remove_handler( modname ) ;
    if( rh ) delete rh ;

    if( BESLog::TheLog()->is_verbose() )
	(*BESLog::TheLog()) << "Removing catalog Container Storage" << endl;
    BESContainerStorageList::TheList()->del_persistence( "catalog" ) ;
}

/** @brief dumps information about this object
 *
 * Displays the pointer value of this instance
 *
 * @param strm C++ i/o stream to dump the information to
 */
void
NCModule::dump( ostream &strm ) const
{
    strm << BESIndent::LMarg << "NCModule::dump - ("
			     << (void *)this << ")" << endl ;
}

extern "C"
{
    BESAbstractModule *maker()
    {
	return new NCModule ;
    }
}

<commit_msg>NCMofule.cc: Indenting<commit_after>// NCModule.cc

// This file is part of bes, A C++ back-end server implementation framework
// for the OPeNDAP Data Access Protocol.

// Copyright (c) 2004,2005 University Corporation for Atmospheric Research
// Author: Patrick West <pwest@ucar.org>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// You can contact University Corporation for Atmospheric Research at
// 3080 Center Green Drive, Boulder, CO 80301

// (c) COPYRIGHT University Corporation for Atmostpheric Research 2004-2005
// Please read the full copyright statement in the file COPYRIGHT_UCAR.
//
// Authors:
//      pwest       Patrick West <pwest@ucar.edu>

#include <iostream>

using std::endl;

#include "NCModule.h"
#include "BESRequestHandlerList.h"
#include "NCRequestHandler.h"
#include "BESContainerStorageList.h"
#include "BESContainerStorageCatalog.h"
#include "BESCatalogDirectory.h"
#include "BESCatalogList.h"
#include "BESLog.h"

#define NC_CATALOG "catalog"

void
 NCModule::initialize(const string & modname)
{
    if (BESLog::TheLog()->is_verbose())
        (*BESLog::TheLog()) << "Initializing NC:" << endl;

    if (BESLog::TheLog()->is_verbose())
        (*BESLog::
         TheLog()) << "    adding " << modname << " request handler" << endl;

    BESRequestHandlerList::TheList()->add_handler(modname,
                                                  new
                                                  NCRequestHandler
                                                  (modname));

    if (BESLog::TheLog()->is_verbose())
        (*BESLog::TheLog()) << "    adding " << NC_CATALOG << " catalog"
            << endl;
    BESCatalogList::TheCatalogList()->
        add_catalog(new BESCatalogDirectory(NC_CATALOG));

    if (BESLog::TheLog()->is_verbose())
        (*BESLog::TheLog()) << "Adding Catalog Container Storage" << endl;
    BESContainerStorageCatalog *csc =
        new BESContainerStorageCatalog(NC_CATALOG);
    BESContainerStorageList::TheList()->add_persistence(csc);
}

void NCModule::terminate(const string & modname)
{
    if (BESLog::TheLog()->is_verbose())
        (*BESLog::TheLog()) << "Removing NC Handlers" << endl;
    BESRequestHandler *rh =
        BESRequestHandlerList::TheList()->remove_handler(modname);
    if (rh)
        delete rh;

    if (BESLog::TheLog()->is_verbose())
        (*BESLog::
         TheLog()) << "Removing catalog Container Storage" << endl;
    BESContainerStorageList::TheList()->del_persistence("catalog");
}

/** @brief dumps information about this object
 *
 * Displays the pointer value of this instance
 *
 * @param strm C++ i/o stream to dump the information to
 */
void NCModule::dump(ostream & strm) const
{
    strm << BESIndent::LMarg << "NCModule::dump - ("
        << (void *) this << ")" << endl;
}

extern "C" BESAbstractModule * maker()
{
    return new NCModule;
}

<|endoftext|>


<commit_before>#include <netinet/tcp.h>

#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include <event2/dns.h>
#include <event2/event.h>
#include <event2/thread.h>
#include <event2/util.h>

#include "config.h"

#include "Protocol.h"
#include "Connection.h"
#include "distributions.h"
#include "Generator.h"
#include "mutilate.h"
#include "binary_protocol.h"
#include "util.h"

#define unlikely(x) __builtin_expect((x),0)

/**
 * Send an ascii get request.
 */
int ProtocolAscii::get_request(const char* key) {
  int l;
  l = evbuffer_add_printf(
    bufferevent_get_output(bev), "get %s\r\n", key);
  if (read_state == IDLE) read_state = WAITING_FOR_GET;
  return l;
}

/**
 * Send an ascii set request.
 */
int ProtocolAscii::set_request(const char* key, const char* value, int len) {
  int l;
  l = evbuffer_add_printf(bufferevent_get_output(bev),
                          "set %s 0 0 %d\r\n", key, len);
  bufferevent_write(bev, value, len);
  bufferevent_write(bev, "\r\n", 2);
  l += len + 2;
  if (read_state == IDLE) read_state = WAITING_FOR_END;
  return l;
}

/**
 * Handle an ascii response.
 */
bool ProtocolAscii::handle_response(evbuffer *input, bool &done) {
  char *buf = NULL;
  int len;
  size_t n_read_out;

  switch (read_state) {

  case WAITING_FOR_GET:
  case WAITING_FOR_END:
    buf = evbuffer_readln(input, &n_read_out, EVBUFFER_EOL_CRLF);
    if (buf == NULL) return false;

    conn->stats.rx_bytes += n_read_out;

    if (!strncmp(buf, "END", 3)) {
      if (read_state == WAITING_FOR_GET) conn->stats.get_misses++;
      read_state = WAITING_FOR_GET;
      done = true;
    } else if (!strncmp(buf, "VALUE", 5)) {
      sscanf(buf, "VALUE %*s %*d %d", &len);

      // FIXME: check key name to see if it corresponds to the op at
      // the head of the op queue?  This will be necessary to
      // support "gets" where there may be misses.

      data_length = len;
      read_state = WAITING_FOR_GET_DATA;
      done = false;
    } else {
      // must be a value line..
      done = false;
    }
    free(buf);
    return true;

  case WAITING_FOR_GET_DATA:
    len = evbuffer_get_length(input);
    if (len >= data_length + 2) {
      evbuffer_drain(input, data_length + 2);
      read_state = WAITING_FOR_END;
      conn->stats.rx_bytes += data_length + 2;
      done = false;
      return true;
    }
    return false;

  default: printf("state: %d\n", read_state); DIE("Unimplemented!");
  }

  DIE("Shouldn't ever reach here...");
}

/**
 * Perform SASL authentication if requested (write).
 */
bool ProtocolBinary::setup_connection_w() {
  if (!opts.sasl) return true;

  string user = string(opts.username);
  string pass = string(opts.password);

  binary_header_t header = {0x80, CMD_SASL, 0, 0, 0, {0}, 0, 0, 0};
  header.key_len = htons(5);
  header.body_len = htonl(6 + user.length() + 1 + pass.length());

  bufferevent_write(bev, &header, 24);
  bufferevent_write(bev, "PLAIN\0", 6);
  bufferevent_write(bev, user.c_str(), user.length() + 1);
  bufferevent_write(bev, pass.c_str(), pass.length());

  return false;
}

/**
 * Perform SASL authentication if requested (read).
 */
bool ProtocolBinary::setup_connection_r(evbuffer* input) {
  if (!opts.sasl) return true;

  bool b;
  return handle_response(input, b);
}

/**
 * Send a binary get request.
 */
int ProtocolBinary::get_request(const char* key) {
  uint16_t keylen = strlen(key);

  // each line is 4-bytes
  binary_header_t h = { 0x80, CMD_GET, htons(keylen),
                        0x00, 0x00, {htons(0)},
                        htonl(keylen) };

  bufferevent_write(bev, &h, 24); // size does not include extras
  bufferevent_write(bev, key, keylen);
  return 24 + keylen;
}

/**
 * Send a binary set request.
 */
int ProtocolBinary::set_request(const char* key, const char* value, int len) {
  uint16_t keylen = strlen(key);

  // each line is 4-bytes
  binary_header_t h = { 0x80, CMD_SET, htons(keylen),
                        0x08, 0x00, {htons(0)},
                        htonl(keylen + 8 + len) };

  bufferevent_write(bev, &h, 32); // With extras
  bufferevent_write(bev, key, keylen);
  bufferevent_write(bev, value, len);
  return 24 + h.body_len;
}

/**
 * Tries to consume a binary response (in its entirety) from an evbuffer.
 *
 * @param input evBuffer to read response from
 * @return  true if consumed, false if not enough data in buffer.
 */
bool ProtocolBinary::handle_response(evbuffer *input, bool &done) {
  // Read the first 24 bytes as a header
  int length = evbuffer_get_length(input);
  if (length < 24) return false;
  binary_header_t* h =
          reinterpret_cast<binary_header_t*>(evbuffer_pullup(input, 24));
  assert(h);

  // Not whole response
  int targetLen = 24 + ntohl(h->body_len);
  if (length < targetLen) return false;

  // If something other than success, count it as a miss
  if (h->opcode == CMD_GET && h->status) {
      conn->stats.get_misses++;
  }

  if (unlikely(h->opcode == CMD_SASL)) {
    if (h->status == RESP_OK) {
      V("SASL authentication succeeded");
    } else {
      DIE("SASL authentication failed");
    }
  }

  evbuffer_drain(input, targetLen);
  conn->stats.rx_bytes += targetLen;
  done = true;
  return true;
}

<commit_msg>Fix incorrect length calculation<commit_after>#include <netinet/tcp.h>

#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include <event2/dns.h>
#include <event2/event.h>
#include <event2/thread.h>
#include <event2/util.h>

#include "config.h"

#include "Protocol.h"
#include "Connection.h"
#include "distributions.h"
#include "Generator.h"
#include "mutilate.h"
#include "binary_protocol.h"
#include "util.h"

#define unlikely(x) __builtin_expect((x),0)

/**
 * Send an ascii get request.
 */
int ProtocolAscii::get_request(const char* key) {
  int l;
  l = evbuffer_add_printf(
    bufferevent_get_output(bev), "get %s\r\n", key);
  if (read_state == IDLE) read_state = WAITING_FOR_GET;
  return l;
}

/**
 * Send an ascii set request.
 */
int ProtocolAscii::set_request(const char* key, const char* value, int len) {
  int l;
  l = evbuffer_add_printf(bufferevent_get_output(bev),
                          "set %s 0 0 %d\r\n", key, len);
  bufferevent_write(bev, value, len);
  bufferevent_write(bev, "\r\n", 2);
  l += len + 2;
  if (read_state == IDLE) read_state = WAITING_FOR_END;
  return l;
}

/**
 * Handle an ascii response.
 */
bool ProtocolAscii::handle_response(evbuffer *input, bool &done) {
  char *buf = NULL;
  int len;
  size_t n_read_out;

  switch (read_state) {

  case WAITING_FOR_GET:
  case WAITING_FOR_END:
    buf = evbuffer_readln(input, &n_read_out, EVBUFFER_EOL_CRLF);
    if (buf == NULL) return false;

    conn->stats.rx_bytes += n_read_out;

    if (!strncmp(buf, "END", 3)) {
      if (read_state == WAITING_FOR_GET) conn->stats.get_misses++;
      read_state = WAITING_FOR_GET;
      done = true;
    } else if (!strncmp(buf, "VALUE", 5)) {
      sscanf(buf, "VALUE %*s %*d %d", &len);

      // FIXME: check key name to see if it corresponds to the op at
      // the head of the op queue?  This will be necessary to
      // support "gets" where there may be misses.

      data_length = len;
      read_state = WAITING_FOR_GET_DATA;
      done = false;
    } else {
      // must be a value line..
      done = false;
    }
    free(buf);
    return true;

  case WAITING_FOR_GET_DATA:
    len = evbuffer_get_length(input);
    if (len >= data_length + 2) {
      evbuffer_drain(input, data_length + 2);
      read_state = WAITING_FOR_END;
      conn->stats.rx_bytes += data_length + 2;
      done = false;
      return true;
    }
    return false;

  default: printf("state: %d\n", read_state); DIE("Unimplemented!");
  }

  DIE("Shouldn't ever reach here...");
}

/**
 * Perform SASL authentication if requested (write).
 */
bool ProtocolBinary::setup_connection_w() {
  if (!opts.sasl) return true;

  string user = string(opts.username);
  string pass = string(opts.password);

  binary_header_t header = {0x80, CMD_SASL, 0, 0, 0, {0}, 0, 0, 0};
  header.key_len = htons(5);
  header.body_len = htonl(6 + user.length() + 1 + pass.length());

  bufferevent_write(bev, &header, 24);
  bufferevent_write(bev, "PLAIN\0", 6);
  bufferevent_write(bev, user.c_str(), user.length() + 1);
  bufferevent_write(bev, pass.c_str(), pass.length());

  return false;
}

/**
 * Perform SASL authentication if requested (read).
 */
bool ProtocolBinary::setup_connection_r(evbuffer* input) {
  if (!opts.sasl) return true;

  bool b;
  return handle_response(input, b);
}

/**
 * Send a binary get request.
 */
int ProtocolBinary::get_request(const char* key) {
  uint16_t keylen = strlen(key);

  // each line is 4-bytes
  binary_header_t h = { 0x80, CMD_GET, htons(keylen),
                        0x00, 0x00, {htons(0)},
                        htonl(keylen) };

  bufferevent_write(bev, &h, 24); // size does not include extras
  bufferevent_write(bev, key, keylen);
  return 24 + keylen;
}

/**
 * Send a binary set request.
 */
int ProtocolBinary::set_request(const char* key, const char* value, int len) {
  uint16_t keylen = strlen(key);

  // each line is 4-bytes
  binary_header_t h = { 0x80, CMD_SET, htons(keylen),
                        0x08, 0x00, {htons(0)},
                        htonl(keylen + 8 + len) };

  bufferevent_write(bev, &h, 32); // With extras
  bufferevent_write(bev, key, keylen);
  bufferevent_write(bev, value, len);
  return 24 + ntohl(h.body_len);
}

/**
 * Tries to consume a binary response (in its entirety) from an evbuffer.
 *
 * @param input evBuffer to read response from
 * @return  true if consumed, false if not enough data in buffer.
 */
bool ProtocolBinary::handle_response(evbuffer *input, bool &done) {
  // Read the first 24 bytes as a header
  int length = evbuffer_get_length(input);
  if (length < 24) return false;
  binary_header_t* h =
          reinterpret_cast<binary_header_t*>(evbuffer_pullup(input, 24));
  assert(h);

  // Not whole response
  int targetLen = 24 + ntohl(h->body_len);
  if (length < targetLen) return false;

  // If something other than success, count it as a miss
  if (h->opcode == CMD_GET && h->status) {
      conn->stats.get_misses++;
  }

  if (unlikely(h->opcode == CMD_SASL)) {
    if (h->status == RESP_OK) {
      V("SASL authentication succeeded");
    } else {
      DIE("SASL authentication failed");
    }
  }

  evbuffer_drain(input, targetLen);
  conn->stats.rx_bytes += targetLen;
  done = true;
  return true;
}

<|endoftext|>


<commit_before>/*
The MIT License(MIT)

Copyright(c) 2016 Joss Whittle

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once

#include <omp.h>
#include "MEL.hpp"

/**
* \file MEL_omp.hpp
*/

namespace MEL {
    namespace OMP {

        /**
         * \defgroup OMP OpenMP Extensions
         * Extensions to MEL that leverage OpenMP for within node paralellism
         */

        namespace Functor {

            /**
             * \ingroup  OMP
             * Maps the given binary functor to the local array of a reduction / accumulate operation, using OpenMP for parallelism
             *
             * \param[in] in		The left hand array for the reduction
             * \param[in] inout		The right hand array for the reduction. This array is modified to reflect the result of the functor on each element
             * \param[in] len		Pointer to a single int representing the number of elements to be processed
             * \param[in] dptr		Pointer to a single derived datatype representing the data to be processed
             */
            template<typename T, T(*F)(T&, T&)>
            void ARRAY_OP_FUNC(T *in, T *inout, int *len, MPI_Datatype *dptr) {
                #pragma omp parallel for
                for (int i = 0; i < *len; ++i)
                    inout[i] = F(in[i], inout[i]);
            };

            /**
             * \ingroup  OMP
             * Maps the given binary functor to the local array of a reduction / accumulate operation, using OpenMP for parallelism
             *
             * \param[in] in		The left hand array for the reduction
             * \param[in] inout		The right hand array for the reduction. This array is modified to reflect the result of the functor on each element
             * \param[in] len		Pointer to a single int representing the number of elements to be processed
             * \param[in] dptr		Pointer to a single derived datatype representing the data to be processed
             */
            template<typename T, T(*F)(T&, T&, MEL::Datatype)>
            void ARRAY_OP_FUNC(T *in, T *inout, int *len, MPI_Datatype *dptr) {
                #pragma omp parallel for
                for (int i = 0; i < *len; ++i)
					inout[i] = F(in[i], inout[i], dptr);
            };
        };

        /**
         * \ingroup  OMP
         * Maps the given binary functor to the local array of a reduction / accumulate operation, using OpenMP for parallelism
         *
         * \see MPI_Op_create
         *
         * \param[in] commute		Is the operation commutative
         * \return					Returns a handle to a new Op
         */
        template<typename T, T(*F)(T&, T&)>
        inline MEL::Op OpCreate(bool commute = true) {
            MPI_Op op;
            MEL_THROW( MPI_Op_create((void(*)(void*, void*, int*, MPI_Datatype*)) MEL::OMP::Functor::ARRAY_OP_FUNC<T, F>, commute, (MPI_Op*) &op), "OMP::Op::CreatOp" );
            return MEL::Op(op);
        };

        /**
         * \ingroup  OMP
         * Maps the given binary functor to the local array of a reduction / accumulate operation, using OpenMP for parallelism
         *
         * \see MPI_Op_create
         *
         * \param[in] commute		Is the operation commutative
         * \return					Returns a handle to a new Op
         */
        template<typename T, T(*F)(T&, T&, MEL::Datatype)>
        inline MEL::Op OpCreate(bool commute = true) {
            MPI_Op op;
            MEL_THROW( MPI_Op_create((void(*)(void*, void*, int*, MPI_Datatype*)) MEL::OMP::Functor::ARRAY_OP_FUNC<T, F>, commute, (MPI_Op*) &op), "OMP::Op::CreatOp" );
            return MEL::Op(op);
        };
    };
};<commit_msg>Revert "bug fix on variable name"<commit_after>/*
The MIT License(MIT)

Copyright(c) 2016 Joss Whittle

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once

#include <omp.h>
#include "MEL.hpp"

/**
* \file MEL_omp.hpp
*/

namespace MEL {
    namespace OMP {

        /**
         * \defgroup OMP OpenMP Extensions
         * Extensions to MEL that leverage OpenMP for within node paralellism
         */

        namespace Functor {

            /**
             * \ingroup  OMP
             * Maps the given binary functor to the local array of a reduction / accumulate operation, using OpenMP for parallelism
             *
             * \param[in] in		The left hand array for the reduction
             * \param[in] inout		The right hand array for the reduction. This array is modified to reflect the result of the functor on each element
             * \param[in] len		Pointer to a single int representing the number of elements to be processed
             * \param[in] dptr		Pointer to a single derived datatype representing the data to be processed
             */
            template<typename T, T(*F)(T&, T&)>
            void ARRAY_OP_FUNC(T *in, T *inout, int *len, MPI_Datatype *dptr) {
                #pragma omp parallel for
                for (int i = 0; i < *len; ++i)
                    inout[i] = F(in[i], inout[i]);
            };

            /**
             * \ingroup  OMP
             * Maps the given binary functor to the local array of a reduction / accumulate operation, using OpenMP for parallelism
             *
             * \param[in] in		The left hand array for the reduction
             * \param[in] inout		The right hand array for the reduction. This array is modified to reflect the result of the functor on each element
             * \param[in] len		Pointer to a single int representing the number of elements to be processed
             * \param[in] dptr		Pointer to a single derived datatype representing the data to be processed
             */
            template<typename T, T(*F)(T&, T&, MEL::Datatype)>
            void ARRAY_OP_FUNC(T *in, T *inout, int *len, MPI_Datatype *dptr) {
                #pragma omp parallel for
                for (int i = 0; i < *len; ++i)
                    inout[i] = F(in[i], inout[i], dt);
            };
        };

        /**
         * \ingroup  OMP
         * Maps the given binary functor to the local array of a reduction / accumulate operation, using OpenMP for parallelism
         *
         * \see MPI_Op_create
         *
         * \param[in] commute		Is the operation commutative
         * \return					Returns a handle to a new Op
         */
        template<typename T, T(*F)(T&, T&)>
        inline MEL::Op OpCreate(bool commute = true) {
            MPI_Op op;
            MEL_THROW( MPI_Op_create((void(*)(void*, void*, int*, MPI_Datatype*)) MEL::OMP::Functor::ARRAY_OP_FUNC<T, F>, commute, (MPI_Op*) &op), "OMP::Op::CreatOp" );
            return MEL::Op(op);
        };

        /**
         * \ingroup  OMP
         * Maps the given binary functor to the local array of a reduction / accumulate operation, using OpenMP for parallelism
         *
         * \see MPI_Op_create
         *
         * \param[in] commute		Is the operation commutative
         * \return					Returns a handle to a new Op
         */
        template<typename T, T(*F)(T&, T&, MEL::Datatype)>
        inline MEL::Op OpCreate(bool commute = true) {
            MPI_Op op;
            MEL_THROW( MPI_Op_create((void(*)(void*, void*, int*, MPI_Datatype*)) MEL::OMP::Functor::ARRAY_OP_FUNC<T, F>, commute, (MPI_Op*) &op), "OMP::Op::CreatOp" );
            return MEL::Op(op);
        };
    };
};<|endoftext|>


<commit_before>/*
The MIT License(MIT)

Copyright(c) 2016 Joss Whittle

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once

#include <omp.h>
#include "MEL.hpp"

/**
* \file MEL_omp.hpp
*/

namespace MEL {
    namespace OMP {

        /**
         * \defgroup OMP OpenMP Extensions
         * Extensions to MEL that leverage OpenMP for within node paralellism
         */

        namespace Functor {

            /**
             * \ingroup  OMP
             * Maps the given binary functor to the local array of a reduction / accumulate operation, using OpenMP for parallelism
             *
             * \param[in] in		The left hand array for the reduction
             * \param[in] inout		The right hand array for the reduction. This array is modified to reflect the result of the functor on each element
             * \param[in] len		Pointer to a single int representing the number of elements to be processed
             * \param[in] dptr		Pointer to a single derived datatype representing the data to be processed
             */
            template<typename T, T(*F)(T&, T&)>
            void ARRAY_OP_FUNC(T *in, T *inout, int *len, MPI_Datatype *dptr) {
                #pragma omp parallel for
                for (int i = 0; i < *len; ++i)
                    inout[i] = F(in[i], inout[i]);
            };

            /**
             * \ingroup  OMP
             * Maps the given binary functor to the local array of a reduction / accumulate operation, using OpenMP for parallelism
             *
             * \param[in] in		The left hand array for the reduction
             * \param[in] inout		The right hand array for the reduction. This array is modified to reflect the result of the functor on each element
             * \param[in] len		Pointer to a single int representing the number of elements to be processed
             * \param[in] dptr		Pointer to a single derived datatype representing the data to be processed
             */
            template<typename T, T(*F)(T&, T&, MEL::Datatype)>
            void ARRAY_OP_FUNC(T *in, T *inout, int *len, MPI_Datatype *dptr) {
                #pragma omp parallel for
                for (int i = 0; i < *len; ++i)
                    inout[i] = F(in[i], inout[i], dt);
            };
        };

        /**
         * \ingroup  OMP
         * Maps the given binary functor to the local array of a reduction / accumulate operation, using OpenMP for parallelism
         *
         * \see MPI_Op_create
         *
         * \param[in] commute		Is the operation commutative
         * \return					Returns a handle to a new Op
         */
        template<typename T, T(*F)(T&, T&)>
        inline MEL::Op OpCreate(bool commute = true) {
            MPI_Op op;
            MEL_THROW( MPI_Op_create((void(*)(void*, void*, int*, MPI_Datatype*)) MEL::OMP::Functor::ARRAY_OP_FUNC<T, F>, commute, (MPI_Op*) &op), "OMP::Op::CreatOp" );
            return MEL::Op(op);
        };

        /**
         * \ingroup  OMP
         * Maps the given binary functor to the local array of a reduction / accumulate operation, using OpenMP for parallelism
         *
         * \see MPI_Op_create
         *
         * \param[in] commute		Is the operation commutative
         * \return					Returns a handle to a new Op
         */
        template<typename T, T(*F)(T&, T&, MEL::Datatype)>
        inline MEL::Op OpCreate(bool commute = true) {
            MPI_Op op;
            MEL_THROW( MPI_Op_create((void(*)(void*, void*, int*, MPI_Datatype*)) MEL::OMP::Functor::ARRAY_OP_FUNC<T, F>, commute, (MPI_Op*) &op), "OMP::Op::CreatOp" );
            return MEL::Op(op);
        };
    };
};<commit_msg>bug fix on variable name<commit_after>/*
The MIT License(MIT)

Copyright(c) 2016 Joss Whittle

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files(the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions :

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#pragma once

#include <omp.h>
#include "MEL.hpp"

/**
* \file MEL_omp.hpp
*/

namespace MEL {
    namespace OMP {

        /**
         * \defgroup OMP OpenMP Extensions
         * Extensions to MEL that leverage OpenMP for within node paralellism
         */

        namespace Functor {

            /**
             * \ingroup  OMP
             * Maps the given binary functor to the local array of a reduction / accumulate operation, using OpenMP for parallelism
             *
             * \param[in] in		The left hand array for the reduction
             * \param[in] inout		The right hand array for the reduction. This array is modified to reflect the result of the functor on each element
             * \param[in] len		Pointer to a single int representing the number of elements to be processed
             * \param[in] dptr		Pointer to a single derived datatype representing the data to be processed
             */
            template<typename T, T(*F)(T&, T&)>
            void ARRAY_OP_FUNC(T *in, T *inout, int *len, MPI_Datatype *dptr) {
                #pragma omp parallel for
                for (int i = 0; i < *len; ++i)
                    inout[i] = F(in[i], inout[i]);
            };

            /**
             * \ingroup  OMP
             * Maps the given binary functor to the local array of a reduction / accumulate operation, using OpenMP for parallelism
             *
             * \param[in] in		The left hand array for the reduction
             * \param[in] inout		The right hand array for the reduction. This array is modified to reflect the result of the functor on each element
             * \param[in] len		Pointer to a single int representing the number of elements to be processed
             * \param[in] dptr		Pointer to a single derived datatype representing the data to be processed
             */
            template<typename T, T(*F)(T&, T&, MEL::Datatype)>
            void ARRAY_OP_FUNC(T *in, T *inout, int *len, MPI_Datatype *dptr) {
                #pragma omp parallel for
                for (int i = 0; i < *len; ++i)
					inout[i] = F(in[i], inout[i], dptr);
            };
        };

        /**
         * \ingroup  OMP
         * Maps the given binary functor to the local array of a reduction / accumulate operation, using OpenMP for parallelism
         *
         * \see MPI_Op_create
         *
         * \param[in] commute		Is the operation commutative
         * \return					Returns a handle to a new Op
         */
        template<typename T, T(*F)(T&, T&)>
        inline MEL::Op OpCreate(bool commute = true) {
            MPI_Op op;
            MEL_THROW( MPI_Op_create((void(*)(void*, void*, int*, MPI_Datatype*)) MEL::OMP::Functor::ARRAY_OP_FUNC<T, F>, commute, (MPI_Op*) &op), "OMP::Op::CreatOp" );
            return MEL::Op(op);
        };

        /**
         * \ingroup  OMP
         * Maps the given binary functor to the local array of a reduction / accumulate operation, using OpenMP for parallelism
         *
         * \see MPI_Op_create
         *
         * \param[in] commute		Is the operation commutative
         * \return					Returns a handle to a new Op
         */
        template<typename T, T(*F)(T&, T&, MEL::Datatype)>
        inline MEL::Op OpCreate(bool commute = true) {
            MPI_Op op;
            MEL_THROW( MPI_Op_create((void(*)(void*, void*, int*, MPI_Datatype*)) MEL::OMP::Functor::ARRAY_OP_FUNC<T, F>, commute, (MPI_Op*) &op), "OMP::Op::CreatOp" );
            return MEL::Op(op);
        };
    };
};<|endoftext|>