<commit_before>/* Copyright 2015-2016 Samsung Electronics Co., Ltd.
 *
 * 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 "iotjs_env.h"

#include <string.h>

namespace iotjs {

/**
 * Construct an instance of Environment.
 */
Environment::Environment()
    : _argc(0)
    , _argv(NULL)
    , _loop(NULL)
    , _state(kInitializing) {
  _config.memstat = false;
  _config.show_opcode = false;
}

/**
 * Release an instance of Environment.
 */
Environment::~Environment() {
  if (_argv) {
    // release command line argument strings.
    // _argv[0] and _argv[1] refer addresses in static memory space.
    // Ohters refer adresses in heap space that is need to be deallocated.
    for (int i = 2; i < _argc; ++i) {
      delete _argv[i];
    }
    delete [] _argv;
  }
}

/**
 * Parse command line arguments
 */
bool Environment::ParseCommandLineArgument(int argc, char** argv) {
  // There must be at least two arguemnts.
  if (argc < 2) {
    fprintf(stderr,
            "usage: iotjs <js> [<iotjs arguments>] [-- <app arguments>]\n");
    return false;
  }

  // Second argument should be IoT.js application.
  char* app = argv[1];
  _argc = 2;

  // Parse IoT.js command line arguments.
  int i = 2;
  while (i < argc) {
    if (!strcmp(argv[i], "--")) {
      ++i;
      break;
    }
    if (!strcmp(argv[i], "--memstat")) {
      _config.memstat = true;
    } else if (!strcmp(argv[i], "--show-opcodes")) {
      _config.show_opcode = true;
    } else {
      fprintf(stderr, "unknown command line argument %s\n", argv[i]);
      return false;
    }
    ++i;
  }

  // Remaining arguments are for application.
  _argv = new char*[_argc + argc - i];
  _argv[0] = argv[0];
  _argv[1] = argv[1];
  while (i < argc) {
    _argv[_argc] = new char[strlen(argv[i]) + 1];
    strcpy(_argv[_argc], argv[i]);
    _argc++;
    i++;
  }

  return true;
}

} // namespace iotjs
<commit_msg>Remove leftover dead code from command line parsing<commit_after>/* Copyright 2015-2016 Samsung Electronics Co., Ltd.
 *
 * 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 "iotjs_env.h"

#include <string.h>

namespace iotjs {

/**
 * Construct an instance of Environment.
 */
Environment::Environment()
    : _argc(0)
    , _argv(NULL)
    , _loop(NULL)
    , _state(kInitializing) {
  _config.memstat = false;
  _config.show_opcode = false;
}

/**
 * Release an instance of Environment.
 */
Environment::~Environment() {
  if (_argv) {
    // release command line argument strings.
    // _argv[0] and _argv[1] refer addresses in static memory space.
    // Ohters refer adresses in heap space that is need to be deallocated.
    for (int i = 2; i < _argc; ++i) {
      delete _argv[i];
    }
    delete [] _argv;
  }
}

/**
 * Parse command line arguments
 */
bool Environment::ParseCommandLineArgument(int argc, char** argv) {
  // There must be at least two arguemnts.
  if (argc < 2) {
    fprintf(stderr,
            "usage: iotjs <js> [<iotjs arguments>] [-- <app arguments>]\n");
    return false;
  }

  // Parse IoT.js command line arguments.
  int i = 2;
  while (i < argc) {
    if (!strcmp(argv[i], "--")) {
      ++i;
      break;
    }
    if (!strcmp(argv[i], "--memstat")) {
      _config.memstat = true;
    } else if (!strcmp(argv[i], "--show-opcodes")) {
      _config.show_opcode = true;
    } else {
      fprintf(stderr, "unknown command line argument %s\n", argv[i]);
      return false;
    }
    ++i;
  }

  // Remaining arguments are for application.
  _argc = 2;
  _argv = new char*[_argc + argc - i];
  _argv[0] = argv[0];
  _argv[1] = argv[1];
  while (i < argc) {
    _argv[_argc] = new char[strlen(argv[i]) + 1];
    strcpy(_argv[_argc], argv[i]);
    _argc++;
    i++;
  }

  return true;
}

} // namespace iotjs
<|endoftext|>


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

/*
 * Copyright (C) 2015 ScyllaDB
 *
 * Modified by ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "locator/network_topology_strategy.hh"
#include "db/consistency_level_type.hh"
#include "db/read_repair_decision.hh"
#include "exceptions/exceptions.hh"
#include "utils/fb_utilities.hh"
#include "gms/inet_address.hh"
#include "database.hh"

#include <iosfwd>
#include <vector>

namespace db {

extern logging::logger cl_logger;

size_t quorum_for(const keyspace& ks);

size_t local_quorum_for(const keyspace& ks, const sstring& dc);

size_t block_for_local_serial(keyspace& ks);

size_t block_for_each_quorum(keyspace& ks);

size_t block_for(keyspace& ks, consistency_level cl);

bool is_datacenter_local(consistency_level l);

bool is_local(gms::inet_address endpoint);

template<typename Range>
inline size_t count_local_endpoints(Range& live_endpoints) {
    return std::count_if(live_endpoints.begin(), live_endpoints.end(), is_local);
}

std::vector<gms::inet_address>
filter_for_query(consistency_level cl,
                 keyspace& ks,
                 std::vector<gms::inet_address> live_endpoints,
                 const std::vector<gms::inet_address>& preferred_endpoints,
                 read_repair_decision read_repair,
                 gms::inet_address* extra,
                 column_family* cf);

std::vector<gms::inet_address> filter_for_query(consistency_level cl,
        keyspace& ks,
        std::vector<gms::inet_address>& live_endpoints,
        const std::vector<gms::inet_address>& preferred_endpoints,
        column_family* cf);

struct dc_node_count {
    size_t live = 0;
    size_t pending = 0;
};

template <typename Range, typename PendingRange = std::array<gms::inet_address, 0>>
inline std::unordered_map<sstring, dc_node_count> count_per_dc_endpoints(
        keyspace& ks,
        Range& live_endpoints,
        const PendingRange& pending_endpoints = std::array<gms::inet_address, 0>()) {
    using namespace locator;

    auto& rs = ks.get_replication_strategy();
    auto& snitch_ptr = i_endpoint_snitch::get_local_snitch_ptr();

    network_topology_strategy* nrs =
            static_cast<network_topology_strategy*>(&rs);

    std::unordered_map<sstring, dc_node_count> dc_endpoints;
    for (auto& dc : nrs->get_datacenters()) {
        dc_endpoints.emplace(dc, dc_node_count());
    }

    //
    // Since live_endpoints are a subset of a get_natural_endpoints() output we
    // will never get any endpoints outside the dataceters from
    // nrs->get_datacenters().
    //
    for (auto& endpoint : live_endpoints) {
        ++(dc_endpoints[snitch_ptr->get_datacenter(endpoint)].live);
    }

    for (auto& endpoint : pending_endpoints) {
        ++(dc_endpoints[snitch_ptr->get_datacenter(endpoint)].pending);
    }

    return dc_endpoints;
}

bool
is_sufficient_live_nodes(consistency_level cl,
                         keyspace& ks,
                         const std::vector<gms::inet_address>& live_endpoints);

template<typename Range, typename PendingRange>
inline bool assure_sufficient_live_nodes_each_quorum(
        consistency_level cl,
        keyspace& ks,
        Range& live_endpoints,
        const PendingRange& pending_endpoints) {
    using namespace locator;

    auto& rs = ks.get_replication_strategy();

    if (rs.get_type() == replication_strategy_type::network_topology) {
        for (auto& entry : count_per_dc_endpoints(ks, live_endpoints, pending_endpoints)) {
            auto dc_block_for = local_quorum_for(ks, entry.first);
            auto dc_live = entry.second.live;
            auto dc_pending = entry.second.pending;

            if (dc_live < dc_block_for + dc_pending) {
                throw exceptions::unavailable_exception(cl, dc_block_for, dc_live);
            }
        }

        return true;
    }

    return false;
}

template<typename Range, typename PendingRange = std::array<gms::inet_address, 0>>
inline void assure_sufficient_live_nodes(
        consistency_level cl,
        keyspace& ks,
        Range& live_endpoints,
        const PendingRange& pending_endpoints = std::array<gms::inet_address, 0>()) {
    size_t need = block_for(ks, cl);

    auto adjust_live_for_error = [] (size_t live, size_t pending) {
        // DowngradingConsistencyRetryPolicy uses alive replicas count from Unavailable
        // exception to adjust CL for retry. When pending node is present CL is increased
        // by 1 internally, so reported number of live nodes has to be adjusted to take
        // this into account
        return pending <= live ? live - pending : 0;
    };

    switch (cl) {
    case consistency_level::ANY:
        // local hint is acceptable, and local node is always live
        break;
    case consistency_level::LOCAL_ONE:
        if (count_local_endpoints(live_endpoints) < count_local_endpoints(pending_endpoints) + 1) {
            throw exceptions::unavailable_exception(cl, 1, 0);
        }
        break;
    case consistency_level::LOCAL_QUORUM: {
        size_t local_live = count_local_endpoints(live_endpoints);
        size_t pending = count_local_endpoints(pending_endpoints);
        if (local_live < need + pending) {
            cl_logger.debug("Local replicas {} are insufficient to satisfy LOCAL_QUORUM requirement of needed {} and pending {}", live_endpoints, local_live, pending);
            throw exceptions::unavailable_exception(cl, need, adjust_live_for_error(local_live, pending));
        }
        break;
    }
    case consistency_level::EACH_QUORUM:
        if (assure_sufficient_live_nodes_each_quorum(cl, ks, live_endpoints, pending_endpoints)) {
            break;
        }
    // Fallthough on purpose for SimpleStrategy
    default:
        size_t live = live_endpoints.size();
        size_t pending = pending_endpoints.size();
        if (live < need + pending) {
            cl_logger.debug("Live nodes {} do not satisfy ConsistencyLevel ({} required, {} pending)", live, need, pending);
            throw exceptions::unavailable_exception(cl, need, adjust_live_for_error(live, pending));
        }
        break;
    }
}

}
<commit_msg>consistency_level: make it more const correct<commit_after>/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*
 * Copyright (C) 2015 ScyllaDB
 *
 * Modified by ScyllaDB
 */

/*
 * This file is part of Scylla.
 *
 * Scylla is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Scylla is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Scylla.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once

#include "locator/network_topology_strategy.hh"
#include "db/consistency_level_type.hh"
#include "db/read_repair_decision.hh"
#include "exceptions/exceptions.hh"
#include "utils/fb_utilities.hh"
#include "gms/inet_address.hh"
#include "database.hh"

#include <iosfwd>
#include <vector>

namespace db {

extern logging::logger cl_logger;

size_t quorum_for(const keyspace& ks);

size_t local_quorum_for(const keyspace& ks, const sstring& dc);

size_t block_for_local_serial(keyspace& ks);

size_t block_for_each_quorum(keyspace& ks);

size_t block_for(keyspace& ks, consistency_level cl);

bool is_datacenter_local(consistency_level l);

bool is_local(gms::inet_address endpoint);

template<typename Range>
inline size_t count_local_endpoints(const Range& live_endpoints) {
    return std::count_if(live_endpoints.begin(), live_endpoints.end(), is_local);
}

std::vector<gms::inet_address>
filter_for_query(consistency_level cl,
                 keyspace& ks,
                 std::vector<gms::inet_address> live_endpoints,
                 const std::vector<gms::inet_address>& preferred_endpoints,
                 read_repair_decision read_repair,
                 gms::inet_address* extra,
                 column_family* cf);

std::vector<gms::inet_address> filter_for_query(consistency_level cl,
        keyspace& ks,
        std::vector<gms::inet_address>& live_endpoints,
        const std::vector<gms::inet_address>& preferred_endpoints,
        column_family* cf);

struct dc_node_count {
    size_t live = 0;
    size_t pending = 0;
};

template <typename Range, typename PendingRange = std::array<gms::inet_address, 0>>
inline std::unordered_map<sstring, dc_node_count> count_per_dc_endpoints(
        keyspace& ks,
        const Range& live_endpoints,
        const PendingRange& pending_endpoints = std::array<gms::inet_address, 0>()) {
    using namespace locator;

    auto& rs = ks.get_replication_strategy();
    auto& snitch_ptr = i_endpoint_snitch::get_local_snitch_ptr();

    network_topology_strategy* nrs =
            static_cast<network_topology_strategy*>(&rs);

    std::unordered_map<sstring, dc_node_count> dc_endpoints;
    for (auto& dc : nrs->get_datacenters()) {
        dc_endpoints.emplace(dc, dc_node_count());
    }

    //
    // Since live_endpoints are a subset of a get_natural_endpoints() output we
    // will never get any endpoints outside the dataceters from
    // nrs->get_datacenters().
    //
    for (auto& endpoint : live_endpoints) {
        ++(dc_endpoints[snitch_ptr->get_datacenter(endpoint)].live);
    }

    for (auto& endpoint : pending_endpoints) {
        ++(dc_endpoints[snitch_ptr->get_datacenter(endpoint)].pending);
    }

    return dc_endpoints;
}

bool
is_sufficient_live_nodes(consistency_level cl,
                         keyspace& ks,
                         const std::vector<gms::inet_address>& live_endpoints);

template<typename Range, typename PendingRange>
inline bool assure_sufficient_live_nodes_each_quorum(
        consistency_level cl,
        keyspace& ks,
        const Range& live_endpoints,
        const PendingRange& pending_endpoints) {
    using namespace locator;

    auto& rs = ks.get_replication_strategy();

    if (rs.get_type() == replication_strategy_type::network_topology) {
        for (auto& entry : count_per_dc_endpoints(ks, live_endpoints, pending_endpoints)) {
            auto dc_block_for = local_quorum_for(ks, entry.first);
            auto dc_live = entry.second.live;
            auto dc_pending = entry.second.pending;

            if (dc_live < dc_block_for + dc_pending) {
                throw exceptions::unavailable_exception(cl, dc_block_for, dc_live);
            }
        }

        return true;
    }

    return false;
}

template<typename Range, typename PendingRange = std::array<gms::inet_address, 0>>
inline void assure_sufficient_live_nodes(
        consistency_level cl,
        keyspace& ks,
        const Range& live_endpoints,
        const PendingRange& pending_endpoints = std::array<gms::inet_address, 0>()) {
    size_t need = block_for(ks, cl);

    auto adjust_live_for_error = [] (size_t live, size_t pending) {
        // DowngradingConsistencyRetryPolicy uses alive replicas count from Unavailable
        // exception to adjust CL for retry. When pending node is present CL is increased
        // by 1 internally, so reported number of live nodes has to be adjusted to take
        // this into account
        return pending <= live ? live - pending : 0;
    };

    switch (cl) {
    case consistency_level::ANY:
        // local hint is acceptable, and local node is always live
        break;
    case consistency_level::LOCAL_ONE:
        if (count_local_endpoints(live_endpoints) < count_local_endpoints(pending_endpoints) + 1) {
            throw exceptions::unavailable_exception(cl, 1, 0);
        }
        break;
    case consistency_level::LOCAL_QUORUM: {
        size_t local_live = count_local_endpoints(live_endpoints);
        size_t pending = count_local_endpoints(pending_endpoints);
        if (local_live < need + pending) {
            cl_logger.debug("Local replicas {} are insufficient to satisfy LOCAL_QUORUM requirement of needed {} and pending {}", live_endpoints, local_live, pending);
            throw exceptions::unavailable_exception(cl, need, adjust_live_for_error(local_live, pending));
        }
        break;
    }
    case consistency_level::EACH_QUORUM:
        if (assure_sufficient_live_nodes_each_quorum(cl, ks, live_endpoints, pending_endpoints)) {
            break;
        }
    // Fallthough on purpose for SimpleStrategy
    default:
        size_t live = live_endpoints.size();
        size_t pending = pending_endpoints.size();
        if (live < need + pending) {
            cl_logger.debug("Live nodes {} do not satisfy ConsistencyLevel ({} required, {} pending)", live, need, pending);
            throw exceptions::unavailable_exception(cl, need, adjust_live_for_error(live, pending));
        }
        break;
    }
}

}
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgProducer/GraphicsContextImplementation>
#include <osg/TextureRectangle>
#include <osg/TextureCubeMap>
#include <osg/Notify>

using namespace osgProducer;

namespace osgProducer
{
    struct MyWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface
    {
        virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier& /*screenIdentifier*/)
        {
            return Producer::RenderSurface::getNumberOfScreens();
        }

        virtual void getScreenResolution(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, unsigned int& width, unsigned int& height)
        {
            osg::ref_ptr<Producer::RenderSurface> rs = new Producer::RenderSurface;
            rs->setHostName(screenIdentifier.hostName);
            rs->setDisplayNum(screenIdentifier.displayNum);
            rs->setScreenNum(screenIdentifier.screenNum);
            rs->getScreenSize(width, height);
        }

        virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits)
        {
            return new GraphicsContextImplementation(traits);
        }
    };

    struct RegisterWindowingSystemInterfaceProxy
    {
        RegisterWindowingSystemInterfaceProxy()
        {
            osg::GraphicsContext::setWindowingSystemInterface(new MyWindowingSystemInterface);
        }

        ~RegisterWindowingSystemInterfaceProxy()
        {
            osg::GraphicsContext::setWindowingSystemInterface(0);
        }
    };

    RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy;
};

GraphicsContextImplementation::GraphicsContextImplementation(Traits* traits)
{
    _traits = traits;

    _rs = new Producer::RenderSurface;
    _rs->setWindowName(traits->windowName);
    _rs->setWindowRectangle(traits->x, traits->y, traits->width, traits->height);
    _rs->useBorder(traits->windowDecoration);
    _rs->setDisplayNum(traits->displayNum);
    _rs->setScreenNum(traits->screenNum);

    // set the visual chooser
    Producer::VisualChooser* rs_vc = _rs->getVisualChooser();
    if (!rs_vc)
    {
        rs_vc = new Producer::VisualChooser;
        _rs->setVisualChooser(rs_vc);
    }

    rs_vc->setRedSize(_traits->red);
    rs_vc->setGreenSize(_traits->green);
    rs_vc->setBlueSize(_traits->blue);
    rs_vc->setAlphaSize(_traits->alpha);

    rs_vc->setDepthSize(_traits->depth);
    rs_vc->setStencilSize(_traits->stencil);

    if (_traits->doubleBuffer) rs_vc->useDoubleBuffer();

    rs_vc->addAttribute( Producer::VisualChooser::RGBA );

    // Always use UseGL
    rs_vc->addAttribute( Producer::VisualChooser::UseGL );

    if (traits->pbuffer)
    {
        _rs->setDrawableType(Producer::RenderSurface::DrawableType_PBuffer);

        if (traits->target)
        {

            _rs->setRenderToTextureOptions(traits->mipMapGeneration ? Producer::RenderSurface::RequestSpaceForMipMaps :
                                                                       Producer::RenderSurface::RenderToTextureOptions_Default);
            _rs->setRenderToTextureMipMapLevel(traits->level);
            _rs->setRenderToTextureMode(traits->alpha>0 ? Producer::RenderSurface::RenderToRGBATexture :
                                                           Producer::RenderSurface::RenderToRGBTexture);

            switch(traits->target)
            {
                case(GL_TEXTURE_1D) :
                    _rs->setRenderToTextureTarget(Producer::RenderSurface::Texture1D);
                    break;
                case(GL_TEXTURE_2D) :
                    _rs->setRenderToTextureTarget(Producer::RenderSurface::Texture2D);
                    break;
                case(GL_TEXTURE_3D) :
                    osg::notify(osg::NOTICE)<<"PBuffer render to Texture3D not supported."<<std::endl;
                    // not supported.
                    // _rs->setRenderToTextureTarget(Producer::RenderSurface::Texture3D);
                    break;
                case(GL_TEXTURE_RECTANGLE) :
                    osg::notify(osg::NOTICE)<<"PBuffer render to TextureRectangle not supported."<<std::endl;
                    // not supported.
                    // _rs->setRenderToTextureTarget(Producer::RenderSurface::TextureRectangle);
                    break;
                case(GL_TEXTURE_CUBE_MAP_POSITIVE_X) :
                case(GL_TEXTURE_CUBE_MAP_NEGATIVE_X) :
                case(GL_TEXTURE_CUBE_MAP_POSITIVE_Y) :
                case(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) :
                case(GL_TEXTURE_CUBE_MAP_POSITIVE_Z) :
                case(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) :
                    _rs->setRenderToTextureTarget(Producer::RenderSurface::TextureCUBE);
                    _rs->setRenderToTextureFace( Producer::RenderSurface::CubeMapFace(traits->target - GL_TEXTURE_CUBE_MAP_POSITIVE_X));
                    break;
            }

        }

    }

    GraphicsContextImplementation* sharedContext = dynamic_cast<GraphicsContextImplementation*>(traits->sharedContext);

    if (sharedContext)
    {
        // different graphics context so we have our own state.
        setState(new osg::State);

        if (sharedContext->getState())
        {
            getState()->setContextID( sharedContext->getState()->getContextID() );
            incrementContextIDUsageCount( sharedContext->getState()->getContextID() );
        }
        else
        {
            getState()->setContextID( osg::GraphicsContext::createNewContextID() );
        }

        // but we share texture objects etc. so we also share the same contextID
        //_rs->realize( 0, sharedContext->_rs->getGLContext() );

    }
    else
    {

        // need to do something here....
        setState( new osg::State );
        getState()->setContextID( osg::GraphicsContext::createNewContextID() );

        //_rs->realize();
    }

    // _rs->useConfigEventThread(false);

    _closeOnDestruction = true;
}

GraphicsContextImplementation::GraphicsContextImplementation(Producer::RenderSurface* rs)
{
    _rs = rs;
    _closeOnDestruction = false;

    _traits = new osg::GraphicsContext::Traits;
    _traits->windowName = _rs->getWindowName();
    _traits->displayNum = _rs->getDisplayNum();
    _traits->screenNum = _rs->getScreenNum();
}

GraphicsContextImplementation::~GraphicsContextImplementation()
{
    if (_closeOnDestruction) close();
}

bool GraphicsContextImplementation::realizeImplementation()
{
    if (_rs.valid())
    {
        GraphicsContextImplementation* sharedContext = dynamic_cast<GraphicsContextImplementation*>(_traits->sharedContext);

        if (sharedContext)
        {
            _rs->realize( 0, sharedContext->_rs->getGLContext() );
        }
        else
        {
            osg::notify(osg::NOTICE)<<"GraphicsContextImplementation::realize"<<std::endl;

            _rs->realize();
        }
        return _rs->isRealized();
    }
    else
    {
        return false;
    }
}

bool GraphicsContextImplementation::makeCurrentImplementation()
{
    if (!_rs)
    {
        osg::notify(osg::NOTICE)<<"Error: GraphicsContextImplementation::makeCurrentImplementation() no RenderSurface."<<std::endl;
        return false;
    }

    if (!isRealized())
    {
        osg::notify(osg::NOTICE)<<"Error: GraphicsContextImplementation::makeCurrentImplementation() not Realized."<<std::endl;
        return false;
    }

//    osg::notify(osg::INFO)<<"GraphicsContextImplementation::makeCurrentImplementation()"<<std::endl;

    _rs->setReadDrawable( 0 );

    // comment out right now, as Producer's setReadDrawable() is doing a call for us.
    // _rs->makeCurrent();

    return true;
}

bool GraphicsContextImplementation::makeContextCurrentImplementation(osg::GraphicsContext* readContext)
{
    if (!_rs) return false;

    GraphicsContextImplementation* readContextImplemention = dynamic_cast<GraphicsContextImplementation*>(readContext);

    if (readContextImplemention)
    {
        _rs->setReadDrawable( readContextImplemention->getRenderSurface() );
    }
    else
    {
        _rs->setReadDrawable( 0 );
    }

    // comment out right now, as Producer's setReadDrawable() is doing a call for us.
    // _rs->makeCurrent();

    return true;
}

bool GraphicsContextImplementation::releaseContextImplementation()
{
    osg::notify(osg::NOTICE)<<"GraphicsContextImplementation::releaseContextImplementation(): not implemented - release not supported under Producer."<<std::endl;
    return false;
}

void GraphicsContextImplementation::closeImplementation()
{
    if (!_rs) return;

    // close render surface by deleting it
    _rs = 0;
}

void GraphicsContextImplementation::bindPBufferToTextureImplementation(GLenum buffer)
{
    if (!_rs) return;

    Producer::RenderSurface::BufferType bufferType = Producer::RenderSurface::FrontBuffer;
    switch(buffer)
    {
        case(GL_BACK): bufferType = Producer::RenderSurface::BackBuffer; break;
        case(GL_FRONT): bufferType = Producer::RenderSurface::FrontBuffer; break;
        default: bufferType = Producer::RenderSurface::FrontBuffer; break;
    }

    _rs->bindPBufferToTexture(bufferType);
}

void GraphicsContextImplementation::swapBuffersImplementation()
{
    _rs->swapBuffers();
}
<commit_msg>Removed the automatic registration of GraphicsContextImplementation.<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgProducer/GraphicsContextImplementation>
#include <osg/TextureRectangle>
#include <osg/TextureCubeMap>
#include <osg/Notify>

using namespace osgProducer;

#if 0
namespace osgProducer
{
    struct MyWindowingSystemInterface : public osg::GraphicsContext::WindowingSystemInterface
    {
        virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier& /*screenIdentifier*/)
        {
            return Producer::RenderSurface::getNumberOfScreens();
        }

        virtual void getScreenResolution(const osg::GraphicsContext::ScreenIdentifier& screenIdentifier, unsigned int& width, unsigned int& height)
        {
            osg::ref_ptr<Producer::RenderSurface> rs = new Producer::RenderSurface;
            rs->setHostName(screenIdentifier.hostName);
            rs->setDisplayNum(screenIdentifier.displayNum);
            rs->setScreenNum(screenIdentifier.screenNum);
            rs->getScreenSize(width, height);
        }

        virtual osg::GraphicsContext* createGraphicsContext(osg::GraphicsContext::Traits* traits)
        {
            return new GraphicsContextImplementation(traits);
        }
    };

    struct RegisterWindowingSystemInterfaceProxy
    {
        RegisterWindowingSystemInterfaceProxy()
        {
            osg::GraphicsContext::setWindowingSystemInterface(new MyWindowingSystemInterface);
        }

        ~RegisterWindowingSystemInterfaceProxy()
        {
            osg::GraphicsContext::setWindowingSystemInterface(0);
        }
    };

    RegisterWindowingSystemInterfaceProxy createWindowingSystemInterfaceProxy;
};
#endif

GraphicsContextImplementation::GraphicsContextImplementation(Traits* traits)
{
    _traits = traits;

    _rs = new Producer::RenderSurface;
    _rs->setWindowName(traits->windowName);
    _rs->setWindowRectangle(traits->x, traits->y, traits->width, traits->height);
    _rs->useBorder(traits->windowDecoration);
    _rs->setDisplayNum(traits->displayNum);
    _rs->setScreenNum(traits->screenNum);

    // set the visual chooser
    Producer::VisualChooser* rs_vc = _rs->getVisualChooser();
    if (!rs_vc)
    {
        rs_vc = new Producer::VisualChooser;
        _rs->setVisualChooser(rs_vc);
    }

    rs_vc->setRedSize(_traits->red);
    rs_vc->setGreenSize(_traits->green);
    rs_vc->setBlueSize(_traits->blue);
    rs_vc->setAlphaSize(_traits->alpha);

    rs_vc->setDepthSize(_traits->depth);
    rs_vc->setStencilSize(_traits->stencil);

    if (_traits->doubleBuffer) rs_vc->useDoubleBuffer();

    rs_vc->addAttribute( Producer::VisualChooser::RGBA );

    // Always use UseGL
    rs_vc->addAttribute( Producer::VisualChooser::UseGL );

    if (traits->pbuffer)
    {
        _rs->setDrawableType(Producer::RenderSurface::DrawableType_PBuffer);

        if (traits->target)
        {

            _rs->setRenderToTextureOptions(traits->mipMapGeneration ? Producer::RenderSurface::RequestSpaceForMipMaps :
                                                                       Producer::RenderSurface::RenderToTextureOptions_Default);
            _rs->setRenderToTextureMipMapLevel(traits->level);
            _rs->setRenderToTextureMode(traits->alpha>0 ? Producer::RenderSurface::RenderToRGBATexture :
                                                           Producer::RenderSurface::RenderToRGBTexture);

            switch(traits->target)
            {
                case(GL_TEXTURE_1D) :
                    _rs->setRenderToTextureTarget(Producer::RenderSurface::Texture1D);
                    break;
                case(GL_TEXTURE_2D) :
                    _rs->setRenderToTextureTarget(Producer::RenderSurface::Texture2D);
                    break;
                case(GL_TEXTURE_3D) :
                    osg::notify(osg::NOTICE)<<"PBuffer render to Texture3D not supported."<<std::endl;
                    // not supported.
                    // _rs->setRenderToTextureTarget(Producer::RenderSurface::Texture3D);
                    break;
                case(GL_TEXTURE_RECTANGLE) :
                    osg::notify(osg::NOTICE)<<"PBuffer render to TextureRectangle not supported."<<std::endl;
                    // not supported.
                    // _rs->setRenderToTextureTarget(Producer::RenderSurface::TextureRectangle);
                    break;
                case(GL_TEXTURE_CUBE_MAP_POSITIVE_X) :
                case(GL_TEXTURE_CUBE_MAP_NEGATIVE_X) :
                case(GL_TEXTURE_CUBE_MAP_POSITIVE_Y) :
                case(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y) :
                case(GL_TEXTURE_CUBE_MAP_POSITIVE_Z) :
                case(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) :
                    _rs->setRenderToTextureTarget(Producer::RenderSurface::TextureCUBE);
                    _rs->setRenderToTextureFace( Producer::RenderSurface::CubeMapFace(traits->target - GL_TEXTURE_CUBE_MAP_POSITIVE_X));
                    break;
            }

        }

    }

    GraphicsContextImplementation* sharedContext = dynamic_cast<GraphicsContextImplementation*>(traits->sharedContext);

    if (sharedContext)
    {
        // different graphics context so we have our own state.
        setState(new osg::State);

        if (sharedContext->getState())
        {
            getState()->setContextID( sharedContext->getState()->getContextID() );
            incrementContextIDUsageCount( sharedContext->getState()->getContextID() );
        }
        else
        {
            getState()->setContextID( osg::GraphicsContext::createNewContextID() );
        }

        // but we share texture objects etc. so we also share the same contextID
        //_rs->realize( 0, sharedContext->_rs->getGLContext() );

    }
    else
    {

        // need to do something here....
        setState( new osg::State );
        getState()->setContextID( osg::GraphicsContext::createNewContextID() );

        //_rs->realize();
    }

    // _rs->useConfigEventThread(false);

    _closeOnDestruction = true;
}

GraphicsContextImplementation::GraphicsContextImplementation(Producer::RenderSurface* rs)
{
    _rs = rs;
    _closeOnDestruction = false;

    _traits = new osg::GraphicsContext::Traits;
    _traits->windowName = _rs->getWindowName();
    _traits->displayNum = _rs->getDisplayNum();
    _traits->screenNum = _rs->getScreenNum();
}

GraphicsContextImplementation::~GraphicsContextImplementation()
{
    if (_closeOnDestruction) close();
}

bool GraphicsContextImplementation::realizeImplementation()
{
    if (_rs.valid())
    {
        GraphicsContextImplementation* sharedContext = dynamic_cast<GraphicsContextImplementation*>(_traits->sharedContext);

        if (sharedContext)
        {
            _rs->realize( 0, sharedContext->_rs->getGLContext() );
        }
        else
        {
            osg::notify(osg::NOTICE)<<"GraphicsContextImplementation::realize"<<std::endl;

            _rs->realize();
        }
        return _rs->isRealized();
    }
    else
    {
        return false;
    }
}

bool GraphicsContextImplementation::makeCurrentImplementation()
{
    if (!_rs)
    {
        osg::notify(osg::NOTICE)<<"Error: GraphicsContextImplementation::makeCurrentImplementation() no RenderSurface."<<std::endl;
        return false;
    }

    if (!isRealized())
    {
        osg::notify(osg::NOTICE)<<"Error: GraphicsContextImplementation::makeCurrentImplementation() not Realized."<<std::endl;
        return false;
    }

//    osg::notify(osg::INFO)<<"GraphicsContextImplementation::makeCurrentImplementation()"<<std::endl;

    _rs->setReadDrawable( 0 );

    // comment out right now, as Producer's setReadDrawable() is doing a call for us.
    // _rs->makeCurrent();

    return true;
}

bool GraphicsContextImplementation::makeContextCurrentImplementation(osg::GraphicsContext* readContext)
{
    if (!_rs) return false;

    GraphicsContextImplementation* readContextImplemention = dynamic_cast<GraphicsContextImplementation*>(readContext);

    if (readContextImplemention)
    {
        _rs->setReadDrawable( readContextImplemention->getRenderSurface() );
    }
    else
    {
        _rs->setReadDrawable( 0 );
    }

    // comment out right now, as Producer's setReadDrawable() is doing a call for us.
    // _rs->makeCurrent();

    return true;
}

bool GraphicsContextImplementation::releaseContextImplementation()
{
    osg::notify(osg::NOTICE)<<"GraphicsContextImplementation::releaseContextImplementation(): not implemented - release not supported under Producer."<<std::endl;
    return false;
}

void GraphicsContextImplementation::closeImplementation()
{
    if (!_rs) return;

    // close render surface by deleting it
    _rs = 0;
}

void GraphicsContextImplementation::bindPBufferToTextureImplementation(GLenum buffer)
{
    if (!_rs) return;

    Producer::RenderSurface::BufferType bufferType = Producer::RenderSurface::FrontBuffer;
    switch(buffer)
    {
        case(GL_BACK): bufferType = Producer::RenderSurface::BackBuffer; break;
        case(GL_FRONT): bufferType = Producer::RenderSurface::FrontBuffer; break;
        default: bufferType = Producer::RenderSurface::FrontBuffer; break;
    }

    _rs->bindPBufferToTexture(bufferType);
}

void GraphicsContextImplementation::swapBuffersImplementation()
{
    _rs->swapBuffers();
}
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_BASE_HH
#define DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_BASE_HH

#include <type_traits>

#include <dune/common/typetraits.hh>
#include <dune/common/dynvector.hh>

#include <dune/stuff/common/disable_warnings.hh>
#if DUNE_VERSION_NEWER(DUNE_COMMON, 3, 9) // EXADUNE
#include <dune/geometry/referenceelements.hh>
#else
#include <dune/geometry/genericreferenceelements.hh>
#endif
#include <dune/stuff/common/reenable_warnings.hh>
#include <dune/stuff/common/exceptions.hh>

#include "../interface.hh"

namespace Dune {
namespace GDT {
namespace Spaces {

// forward, to allow for specialization
template <class ImpTraits, int domainDim, class RangeFieldImp, int rangeDim, int rangeDimCols = 1>
class ContinuousLagrangeBase
{
  static_assert(AlwaysFalse<ImpTraits>::value, "Untested for these dimensions!");
};

template <class ImpTraits, int domainDim, class RangeFieldImp, int rangeDim>
class ContinuousLagrangeBase<ImpTraits, domainDim, RangeFieldImp, rangeDim, 1> : public SpaceInterface<ImpTraits>
{
  typedef SpaceInterface<ImpTraits> BaseType;
  typedef ContinuousLagrangeBase<ImpTraits, domainDim, RangeFieldImp, rangeDim, 1> ThisType;

  static constexpr RangeFieldImp compare_tolerance_ = 1e-13;

public:
  typedef ImpTraits Traits;

  using BaseType::polOrder;

  using typename BaseType::DomainFieldType;
  using BaseType::dimDomain;
  using typename BaseType::DomainType;

  typedef typename Traits::RangeFieldType RangeFieldType;
  using BaseType::dimRange;
  using BaseType::dimRangeCols;

  using typename BaseType::EntityType;
  using typename BaseType::IntersectionType;
  using typename BaseType::BoundaryInfoType;
  using typename BaseType::PatternType;

  virtual ~ContinuousLagrangeBase()
  {
  }

  using BaseType::compute_pattern;

  template <class G, class S>
  PatternType compute_pattern(const GridView<G>& local_grid_view, const SpaceInterface<S>& ansatz_space) const
  {
    return BaseType::compute_volume_pattern(local_grid_view, ansatz_space);
  }

  virtual std::vector<DomainType> lagrange_points(const EntityType& entity) const
  {
    // check
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    assert(this->grid_view()->indexSet().contains(entity));
    // get the basis and reference element
    const auto basis              = this->base_function_set(entity);
    const auto& reference_element = ReferenceElements<DomainFieldType, dimDomain>::general(entity.type());
    const int num_vertices = reference_element.size(dimDomain);
    assert(num_vertices >= 0);
    assert(size_t(num_vertices) == basis.size() && "This should not happen with polOrder 1!");
    // prepare return vector
    std::vector<DomainType> local_vertices(num_vertices, DomainType(0));
    if (this->tmp_basis_values_.size() < basis.size())
      this->tmp_basis_values_.resize(basis.size());
    // loop over all vertices
    for (int ii = 0; ii < num_vertices; ++ii) {
      // get the local coordinate of the iith vertex
      const auto local_vertex = reference_element.position(ii, dimDomain);
      // evaluate the basefunctionset
      basis.evaluate(local_vertex, this->tmp_basis_values_);
      // find the basis function that evaluates to one here (has to be only one!)
      size_t ones     = 0;
      size_t zeros    = 0;
      size_t failures = 0;
      for (size_t jj = 0; jj < basis.size(); ++jj) {
        if (std::abs(this->tmp_basis_values_[jj][0] - RangeFieldType(1)) < compare_tolerance_) {
          local_vertices[jj] = local_vertex;
          ++ones;
        } else if (std::abs(this->tmp_basis_values_[jj][0]) < compare_tolerance_)
          ++zeros;
        else
          ++failures;
      }
      assert(ones == 1 && zeros == (basis.size() - 1) && failures == 0 && "This must not happen for polOrder 1!");
    }
    return local_vertices;
  } // ... lagrange_points(...)

  virtual std::set<size_t> local_dirichlet_DoFs(const EntityType& entity, const BoundaryInfoType& boundaryInfo) const
  {
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    // check
    assert(this->grid_view()->indexSet().contains(entity));
    // prepare
    std::set<size_t> localDirichletDofs;
    std::vector<DomainType> dirichlet_vertices;
    // get all dirichlet vertices of this entity, therefore
    // * loop over all intersections
    const auto intersection_it_end = this->grid_view()->iend(entity);
    for (auto intersection_it = this->grid_view()->ibegin(entity); intersection_it != intersection_it_end;
         ++intersection_it) {
      // only work on dirichlet ones
      const auto& intersection = *intersection_it;
      // actual dirichlet intersections + process boundaries for parallel runs
      if (boundaryInfo.dirichlet(intersection) || (!intersection.neighbor() && !intersection.boundary())) {
        // and get the vertices of the intersection
        const auto geometry = intersection.geometry();
        for (int cc = 0; cc < geometry.corners(); ++cc)
          dirichlet_vertices.emplace_back(entity.geometry().local(geometry.corner(cc)));
      } // only work on dirichlet ones
    } // loop over all intersections
    // find the corresponding basis functions
    const auto basis = this->base_function_set(entity);
    if (this->tmp_basis_values_.size() < basis.size())
      this->tmp_basis_values_.resize(basis.size());
    for (size_t cc = 0; cc < dirichlet_vertices.size(); ++cc) {
      // find the basis function that evaluates to one here (has to be only one!)
      basis.evaluate(dirichlet_vertices[cc], this->tmp_basis_values_);
      size_t ones     = 0;
      size_t zeros    = 0;
      size_t failures = 0;
      for (size_t jj = 0; jj < basis.size(); ++jj) {
        if (std::abs(this->tmp_basis_values_[jj][0] - RangeFieldType(1)) < compare_tolerance_) {
          localDirichletDofs.insert(jj);
          ++ones;
        } else if (std::abs(this->tmp_basis_values_[jj][0]) < compare_tolerance_)
          ++zeros;
        else
          ++failures;
      }
      assert(ones == 1 && zeros == (basis.size() - 1) && failures == 0 && "This must not happen for polOrder 1!");
    }
    return localDirichletDofs;
  } // ... local_dirichlet_DoFs(...)

private:
  template <class C, bool set_row>
  struct DirichletConstraints;
  template <class C>
  struct DirichletConstraints<C, true>
  {
    static RangeFieldType value()
    {
      return RangeFieldType(1);
    }
  };
  template <class C>
  struct DirichletConstraints<C, false>
  {
    static RangeFieldType value()
    {
      return RangeFieldType(0);
    }
  };

  template <class T, bool set_row>
  void compute_local_constraints(const SpaceInterface<T>& other, const EntityType& entity,
                                 Constraints::Dirichlet<IntersectionType, RangeFieldType, set_row>& ret) const
  {
    // check
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    assert(this->grid_view()->indexSet().contains(entity));
    typedef DirichletConstraints<Constraints::Dirichlet<IntersectionType, RangeFieldType, set_row>, set_row> SetRow;
    const std::set<size_t> localDirichletDofs = this->local_dirichlet_DoFs(entity, ret.gridBoundary());
    const size_t numRows = localDirichletDofs.size();
    if (numRows > 0) {
      const size_t numCols = this->mapper().numDofs(entity);
      ret.setSize(numRows, numCols);
      this->mapper().globalIndices(entity, tmpMappedRows_);
      other.mapper().globalIndices(entity, tmpMappedCols_);
      size_t localRow = 0;
      const RangeFieldType zero(0);
      for (auto localDirichletDofIt = localDirichletDofs.begin(); localDirichletDofIt != localDirichletDofs.end();
           ++localDirichletDofIt) {
        const size_t& localDirichletDofIndex = *localDirichletDofIt;
        ret.globalRow(localRow) = tmpMappedRows_[localDirichletDofIndex];
        for (size_t jj = 0; jj < ret.cols(); ++jj) {
          ret.globalCol(jj) = tmpMappedCols_[jj];
          if (tmpMappedCols_[jj] == tmpMappedRows_[localDirichletDofIndex])
            ret.value(localRow, jj) = SetRow::value();
          else
            ret.value(localRow, jj) = zero;
        }
        ++localRow;
      }
    } else {
      ret.setSize(0, 0);
    }
  } // ... compute_local_constraints(..., Dirichlet< ..., true >)

public:
  template <bool set>
  void local_constraints(const EntityType& entity,
                         Constraints::Dirichlet<IntersectionType, RangeFieldType, set>& ret) const
  {
    local_constraints(*this, entity, ret);
  }

  virtual void local_constraints(const ThisType& other, const EntityType& entity,
                                 Constraints::Dirichlet<IntersectionType, RangeFieldType, true>& ret) const
  {
    compute_local_constraints(other, entity, ret);
  }

  virtual void local_constraints(const ThisType& other, const EntityType& entity,
                                 Constraints::Dirichlet<IntersectionType, RangeFieldType, false>& ret) const
  {
    compute_local_constraints(other, entity, ret);
  }

protected:
  mutable Dune::DynamicVector<size_t> tmpMappedRows_;
  mutable Dune::DynamicVector<size_t> tmpMappedCols_;
}; // class ContinuousLagrangeBase

} // namespace Spaces
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_BASE_HH
<commit_msg>[spaces.continuouslagrange.base] fix (clang) compile error<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_BASE_HH
#define DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_BASE_HH

#include <type_traits>

#include <dune/common/typetraits.hh>
#include <dune/common/dynvector.hh>
#include <dune/common/version.hh>

#include <dune/stuff/common/disable_warnings.hh>
#if DUNE_VERSION_NEWER(DUNE_COMMON, 3, 9) // EXADUNE
#include <dune/geometry/referenceelements.hh>
#else
#include <dune/geometry/genericreferenceelements.hh>
#endif
#include <dune/stuff/common/reenable_warnings.hh>
#include <dune/stuff/common/exceptions.hh>

#include "../interface.hh"

namespace Dune {
namespace GDT {
namespace Spaces {

// forward, to allow for specialization
template <class ImpTraits, int domainDim, class RangeFieldImp, int rangeDim, int rangeDimCols = 1>
class ContinuousLagrangeBase
{
  static_assert(AlwaysFalse<ImpTraits>::value, "Untested for these dimensions!");
};

template <class ImpTraits, int domainDim, class RangeFieldImp, int rangeDim>
class ContinuousLagrangeBase<ImpTraits, domainDim, RangeFieldImp, rangeDim, 1> : public SpaceInterface<ImpTraits>
{
  typedef SpaceInterface<ImpTraits> BaseType;
  typedef ContinuousLagrangeBase<ImpTraits, domainDim, RangeFieldImp, rangeDim, 1> ThisType;

  static constexpr RangeFieldImp compare_tolerance_ = 1e-13;

public:
  typedef ImpTraits Traits;

  using BaseType::polOrder;

  using typename BaseType::DomainFieldType;
  using BaseType::dimDomain;
  using typename BaseType::DomainType;

  typedef typename Traits::RangeFieldType RangeFieldType;
  using BaseType::dimRange;
  using BaseType::dimRangeCols;

  using typename BaseType::EntityType;
  using typename BaseType::IntersectionType;
  using typename BaseType::BoundaryInfoType;
  using typename BaseType::PatternType;

  virtual ~ContinuousLagrangeBase()
  {
  }

  using BaseType::compute_pattern;

  template <class G, class S>
  PatternType compute_pattern(const GridView<G>& local_grid_view, const SpaceInterface<S>& ansatz_space) const
  {
    return BaseType::compute_volume_pattern(local_grid_view, ansatz_space);
  }

  virtual std::vector<DomainType> lagrange_points(const EntityType& entity) const
  {
    // check
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    assert(this->grid_view()->indexSet().contains(entity));
    // get the basis and reference element
    const auto basis              = this->base_function_set(entity);
    const auto& reference_element = ReferenceElements<DomainFieldType, dimDomain>::general(entity.type());
    const int num_vertices = reference_element.size(dimDomain);
    assert(num_vertices >= 0);
    assert(size_t(num_vertices) == basis.size() && "This should not happen with polOrder 1!");
    // prepare return vector
    std::vector<DomainType> local_vertices(num_vertices, DomainType(0));
    if (this->tmp_basis_values_.size() < basis.size())
      this->tmp_basis_values_.resize(basis.size());
    // loop over all vertices
    for (int ii = 0; ii < num_vertices; ++ii) {
      // get the local coordinate of the iith vertex
      const auto local_vertex = reference_element.position(ii, dimDomain);
      // evaluate the basefunctionset
      basis.evaluate(local_vertex, this->tmp_basis_values_);
      // find the basis function that evaluates to one here (has to be only one!)
      size_t ones     = 0;
      size_t zeros    = 0;
      size_t failures = 0;
      for (size_t jj = 0; jj < basis.size(); ++jj) {
        if (std::abs(this->tmp_basis_values_[jj][0] - RangeFieldType(1)) < compare_tolerance_) {
          local_vertices[jj] = local_vertex;
          ++ones;
        } else if (std::abs(this->tmp_basis_values_[jj][0]) < compare_tolerance_)
          ++zeros;
        else
          ++failures;
      }
      assert(ones == 1 && zeros == (basis.size() - 1) && failures == 0 && "This must not happen for polOrder 1!");
    }
    return local_vertices;
  } // ... lagrange_points(...)

  virtual std::set<size_t> local_dirichlet_DoFs(const EntityType& entity, const BoundaryInfoType& boundaryInfo) const
  {
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    // check
    assert(this->grid_view()->indexSet().contains(entity));
    // prepare
    std::set<size_t> localDirichletDofs;
    std::vector<DomainType> dirichlet_vertices;
    // get all dirichlet vertices of this entity, therefore
    // * loop over all intersections
    const auto intersection_it_end = this->grid_view()->iend(entity);
    for (auto intersection_it = this->grid_view()->ibegin(entity); intersection_it != intersection_it_end;
         ++intersection_it) {
      // only work on dirichlet ones
      const auto& intersection = *intersection_it;
      // actual dirichlet intersections + process boundaries for parallel runs
      if (boundaryInfo.dirichlet(intersection) || (!intersection.neighbor() && !intersection.boundary())) {
        // and get the vertices of the intersection
        const auto geometry = intersection.geometry();
        for (int cc = 0; cc < geometry.corners(); ++cc)
          dirichlet_vertices.emplace_back(entity.geometry().local(geometry.corner(cc)));
      } // only work on dirichlet ones
    } // loop over all intersections
    // find the corresponding basis functions
    const auto basis = this->base_function_set(entity);
    if (this->tmp_basis_values_.size() < basis.size())
      this->tmp_basis_values_.resize(basis.size());
    for (size_t cc = 0; cc < dirichlet_vertices.size(); ++cc) {
      // find the basis function that evaluates to one here (has to be only one!)
      basis.evaluate(dirichlet_vertices[cc], this->tmp_basis_values_);
      size_t ones     = 0;
      size_t zeros    = 0;
      size_t failures = 0;
      for (size_t jj = 0; jj < basis.size(); ++jj) {
        if (std::abs(this->tmp_basis_values_[jj][0] - RangeFieldType(1)) < compare_tolerance_) {
          localDirichletDofs.insert(jj);
          ++ones;
        } else if (std::abs(this->tmp_basis_values_[jj][0]) < compare_tolerance_)
          ++zeros;
        else
          ++failures;
      }
      assert(ones == 1 && zeros == (basis.size() - 1) && failures == 0 && "This must not happen for polOrder 1!");
    }
    return localDirichletDofs;
  } // ... local_dirichlet_DoFs(...)

private:
  template <class C, bool set_row>
  struct DirichletConstraints;
  template <class C>
  struct DirichletConstraints<C, true>
  {
    static RangeFieldType value()
    {
      return RangeFieldType(1);
    }
  };
  template <class C>
  struct DirichletConstraints<C, false>
  {
    static RangeFieldType value()
    {
      return RangeFieldType(0);
    }
  };

  template <class T, bool set_row>
  void compute_local_constraints(const SpaceInterface<T>& other, const EntityType& entity,
                                 Constraints::Dirichlet<IntersectionType, RangeFieldType, set_row>& ret) const
  {
    // check
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    assert(this->grid_view()->indexSet().contains(entity));
    typedef DirichletConstraints<Constraints::Dirichlet<IntersectionType, RangeFieldType, set_row>, set_row> SetRow;
    const std::set<size_t> localDirichletDofs = this->local_dirichlet_DoFs(entity, ret.gridBoundary());
    const size_t numRows = localDirichletDofs.size();
    if (numRows > 0) {
      const size_t numCols = this->mapper().numDofs(entity);
      ret.setSize(numRows, numCols);
      this->mapper().globalIndices(entity, tmpMappedRows_);
      other.mapper().globalIndices(entity, tmpMappedCols_);
      size_t localRow = 0;
      const RangeFieldType zero(0);
      for (auto localDirichletDofIt = localDirichletDofs.begin(); localDirichletDofIt != localDirichletDofs.end();
           ++localDirichletDofIt) {
        const size_t& localDirichletDofIndex = *localDirichletDofIt;
        ret.globalRow(localRow) = tmpMappedRows_[localDirichletDofIndex];
        for (size_t jj = 0; jj < ret.cols(); ++jj) {
          ret.globalCol(jj) = tmpMappedCols_[jj];
          if (tmpMappedCols_[jj] == tmpMappedRows_[localDirichletDofIndex])
            ret.value(localRow, jj) = SetRow::value();
          else
            ret.value(localRow, jj) = zero;
        }
        ++localRow;
      }
    } else {
      ret.setSize(0, 0);
    }
  } // ... compute_local_constraints(..., Dirichlet< ..., true >)

public:
  template <bool set>
  void local_constraints(const EntityType& entity,
                         Constraints::Dirichlet<IntersectionType, RangeFieldType, set>& ret) const
  {
    local_constraints(*this, entity, ret);
  }

  virtual void local_constraints(const ThisType& other, const EntityType& entity,
                                 Constraints::Dirichlet<IntersectionType, RangeFieldType, true>& ret) const
  {
    compute_local_constraints(other, entity, ret);
  }

  virtual void local_constraints(const ThisType& other, const EntityType& entity,
                                 Constraints::Dirichlet<IntersectionType, RangeFieldType, false>& ret) const
  {
    compute_local_constraints(other, entity, ret);
  }

protected:
  mutable Dune::DynamicVector<size_t> tmpMappedRows_;
  mutable Dune::DynamicVector<size_t> tmpMappedCols_;
}; // class ContinuousLagrangeBase

} // namespace Spaces
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_BASE_HH
<|endoftext|>


<commit_before>/*
 * Copyright 2017-2019 Leonid Yuriev <leo@yuriev.ru>
 * and other libmdbx authors: please see AUTHORS file.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */

#include "test.h"
#include <cmath>
#include <queue>

static unsigned edge2window(uint64_t edge, unsigned window_max) {
  const double rnd = u64_to_double1(bleach64(edge));
  const unsigned window = window_max - std::lrint(std::pow(window_max, rnd));
  return window - (window > 0);
}

static unsigned edge2count(uint64_t edge, unsigned count_max) {
  const double rnd = u64_to_double1(prng64_map1_white(edge));
  const unsigned count = std::lrint(std::pow(count_max, rnd));
  return count;
}

bool testcase_ttl::run() {
  db_open();

  txn_begin(false);
  MDBX_dbi dbi = db_table_open(true);
  int rc = mdbx_drop(txn_guard.get(), dbi, false);
  if (unlikely(rc != MDBX_SUCCESS))
    failure_perror("mdbx_drop(delete=false)", rc);
  txn_end(false);

  /* LY: тест "эмуляцией time-to-live":
   *  - организуется "скользящее окно", которое двигается вперед вдоль
   *    числовой оси каждую транзакцию.
   *  - по переднему краю "скользящего окна" записи добавляются в таблицу,
   *    а по заднему удаляются.
   *  - количество добавляемых/удаляемых записей псевдослучайно зависит
   *    от номера транзакции, но с экспоненциальным распределением.
   *  - размер "скользящего окна" также псевдослучайно зависит от номера
   *    транзакции с "отрицательным" экспоненциальным распределением
   *    MAX_WIDTH - exp(rnd(N)), при уменьшении окна сдвигается задний
   *    край и удаляются записи позади него.
   *
   *  Таким образом имитируется поведение таблицы с TTL: записи стохастически
   *  добавляются и удаляются, но изредка происходят массивные удаления.
   */

  /* LY: для параметризации используем подходящие параметры, которые не имеют
   * здесь смысла в первоначальном значении */
  const unsigned window_max =
      (config.params.batch_read > 999) ? config.params.batch_read : 1000;
  const unsigned count_max =
      (config.params.batch_write > 999) ? config.params.batch_write : 1000;
  log_info("ttl: using `batch_read` value %u for window_max", window_max);
  log_info("ttl: using `batch_write` value %u for count_max", count_max);

  uint64_t seed = prng64_map2_white(config.params.keygen.seed) + config.actor_id;
  keyvalue_maker.setup(config.params, config.actor_id, 0 /* thread_number */);
  key = keygen::alloc(config.params.keylen_max);
  data = keygen::alloc(config.params.datalen_max);
  const unsigned insert_flags = (config.params.table_flags & MDBX_DUPSORT)
                                    ? MDBX_NODUPDATA
                                    : MDBX_NODUPDATA | MDBX_NOOVERWRITE;

  std::queue<std::pair<uint64_t, unsigned>> fifo;
  uint64_t serial = 0;
  while (should_continue()) {
    if (!txn_guard)
      txn_begin(false);
    const uint64_t salt = prng64_white(seed)/* mdbx_txn_id(txn_guard.get()) */;

    const unsigned window = edge2window(salt, window_max);
    log_trace("ttl: window %u at %" PRIu64, window, salt);
    while (fifo.size() > window) {
      uint64_t tail_serial = fifo.front().first;
      const unsigned tail_count = fifo.front().second;
      log_trace("ttl: pop-tail (serial %" PRIu64 ", count %u)", tail_serial,
                tail_count);
      fifo.pop();
      for (unsigned n = 0; n < tail_count; ++n) {
        log_trace("ttl: remove-tail %" PRIu64, serial);
        generate_pair(tail_serial);
        int err = mdbx_del(txn_guard.get(), dbi, &key->value, &data->value);
        if (unlikely(err != MDBX_SUCCESS))
          failure_perror("mdbx_del(tail)", err);
        if (unlikely(!keyvalue_maker.increment(tail_serial, 1)))
          failure("ttl: unexpected key-space overflow on the tail");
      }
    }

    txn_restart(false, false);
    const unsigned head_count = edge2count(salt, count_max);
    fifo.push(std::make_pair(serial, head_count));
    log_trace("ttl: push-head (serial %" PRIu64 ", count %u)", serial,
              head_count);

    for (unsigned n = 0; n < head_count; ++n) {
      log_trace("ttl: insert-head %" PRIu64, serial);
      generate_pair(serial);
      int err = mdbx_put(txn_guard.get(), dbi, &key->value, &data->value,
                         insert_flags);
      if (unlikely(err != MDBX_SUCCESS))
        failure_perror("mdbx_put(head)", err);

      if (unlikely(!keyvalue_maker.increment(serial, 1)))
        failure("uphill: unexpected key-space overflow");
    }

    txn_end(false);
    report(1);
  }

  if (dbi) {
    if (config.params.drop_table && !mode_readonly()) {
      txn_begin(false);
      db_table_drop(dbi);
      txn_end(false);
    } else
      db_table_close(dbi);
  }
  return true;
}
<commit_msg>mdbx-test: refine 'ttl' testcase.<commit_after>/*
 * Copyright 2017-2019 Leonid Yuriev <leo@yuriev.ru>
 * and other libmdbx authors: please see AUTHORS file.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted only as authorized by the OpenLDAP
 * Public License.
 *
 * A copy of this license is available in the file LICENSE in the
 * top-level directory of the distribution or, alternatively, at
 * <http://www.OpenLDAP.org/license.html>.
 */

#include "test.h"
#include <cmath>
#include <deque>

static unsigned edge2window(uint64_t edge, unsigned window_max) {
  const double rnd = u64_to_double1(bleach64(edge));
  const unsigned window = window_max - std::lrint(std::pow(window_max, rnd));
  return window;
}

static unsigned edge2count(uint64_t edge, unsigned count_max) {
  const double rnd = u64_to_double1(prng64_map1_white(edge));
  const unsigned count = std::lrint(std::pow(count_max, rnd));
  return count;
}

bool testcase_ttl::run() {
  db_open();

  txn_begin(false);
  MDBX_dbi dbi = db_table_open(true);
  db_table_clear(dbi);
  txn_end(false);

  /* LY: тест "эмуляцией time-to-live":
   *  - организуется "скользящее окно", которое двигается вперед вдоль
   *    числовой оси каждую транзакцию.
   *  - по переднему краю "скользящего окна" записи добавляются в таблицу,
   *    а по заднему удаляются.
   *  - количество добавляемых/удаляемых записей псевдослучайно зависит
   *    от номера транзакции, но с экспоненциальным распределением.
   *  - размер "скользящего окна" также псевдослучайно зависит от номера
   *    транзакции с "отрицательным" экспоненциальным распределением
   *    MAX_WIDTH - exp(rnd(N)), при уменьшении окна сдвигается задний
   *    край и удаляются записи позади него.
   *
   *  Таким образом имитируется поведение таблицы с TTL: записи стохастически
   *  добавляются и удаляются, но изредка происходят массивные удаления.
   */

  /* LY: для параметризации используем подходящие параметры, которые не имеют
   * здесь смысла в первоначальном значении */
  const unsigned window_max =
      (config.params.batch_read > 999) ? config.params.batch_read : 1000;
  const unsigned count_max =
      (config.params.batch_write > 999) ? config.params.batch_write : 1000;
  log_info("ttl: using `batch_read` value %u for window_max", window_max);
  log_info("ttl: using `batch_write` value %u for count_max", count_max);

  uint64_t seed =
      prng64_map2_white(config.params.keygen.seed) + config.actor_id;
  keyvalue_maker.setup(config.params, config.actor_id, 0 /* thread_number */);
  key = keygen::alloc(config.params.keylen_max);
  data = keygen::alloc(config.params.datalen_max);
  const unsigned insert_flags = (config.params.table_flags & MDBX_DUPSORT)
                                    ? MDBX_NODUPDATA
                                    : MDBX_NODUPDATA | MDBX_NOOVERWRITE;

  std::deque<std::pair<uint64_t, unsigned>> fifo;
  uint64_t serial = 0;
  while (should_continue()) {
    if (!txn_guard)
      txn_begin(false);
    const uint64_t salt = prng64_white(seed) /* mdbx_txn_id(txn_guard.get()) */;

    const unsigned window_width = edge2window(salt, window_max);
    const unsigned head_count = edge2count(salt, count_max);
    log_info("ttl: step #%zu (serial %" PRIu64
             ", window %u, count %u) salt %" PRIu64,
             nops_completed, serial, window_width, head_count, salt);

    if (window_width) {
      while (fifo.size() > window_width) {
        uint64_t tail_serial = fifo.back().first;
        const unsigned tail_count = fifo.back().second;
        log_trace("ttl: pop-tail (serial %" PRIu64 ", count %u)", tail_serial,
                  tail_count);
        fifo.pop_back();
        for (unsigned n = 0; n < tail_count; ++n) {
          log_trace("ttl: remove-tail %" PRIu64, serial);
          generate_pair(tail_serial);
          int err = mdbx_del(txn_guard.get(), dbi, &key->value, &data->value);
          if (unlikely(err != MDBX_SUCCESS))
            failure_perror("mdbx_del(tail)", err);
          if (unlikely(!keyvalue_maker.increment(tail_serial, 1)))
            failure("ttl: unexpected key-space overflow on the tail");
        }
      }
    } else {
      log_trace("ttl: purge state");
      db_table_clear(dbi);
      fifo.clear();
    }

    txn_restart(false, false);
    fifo.push_front(std::make_pair(serial, head_count));

    for (unsigned n = 0; n < head_count; ++n) {
      log_trace("ttl: insert-head %" PRIu64, serial);
      generate_pair(serial);
      int err = mdbx_put(txn_guard.get(), dbi, &key->value, &data->value,
                         insert_flags);
      if (unlikely(err != MDBX_SUCCESS))
        failure_perror("mdbx_put(head)", err);

      if (unlikely(!keyvalue_maker.increment(serial, 1)))
        failure("uphill: unexpected key-space overflow");
    }

    txn_end(false);
    report(1);
  }

  if (dbi) {
    if (config.params.drop_table && !mode_readonly()) {
      txn_begin(false);
      db_table_drop(dbi);
      txn_end(false);
    } else
      db_table_close(dbi);
  }
  return true;
}
<|endoftext|>


<commit_before>//=============================================================================================================
/**
 * @file     natus.cpp
 * @author   Lorenz Esch <lesch@mgh.harvard.edu>
 * @version  dev
 * @date     June, 2018
 *
 * @section  LICENSE
 *
 * Copyright (C) 2018, Lorenz Esch. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 * the following conditions are met:
 *     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *       following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
 *       the following disclaimer in the documentation and/or other materials provided with the distribution.
 *     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
 *       to endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * @brief    Contains the definition of the Natus class.
 *
 */

//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "natus.h"
#include "natusproducer.h"
#include "FormFiles/natussetup.h"

#include <fiff/fiff.h>
#include <scMeas/realtimemultisamplearray.h>

//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QSettings>

//=============================================================================================================
// EIGEN INCLUDES
//=============================================================================================================

//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace NATUSPLUGIN;
using namespace SCSHAREDLIB;
using namespace SCMEASLIB;
using namespace FIFFLIB;
using namespace Eigen;
using namespace IOBUFFER;

//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

Natus::Natus()
: m_iSamplingFreq(2048)
, m_iNumberChannels(46)
, m_iSamplesPerBlock(256)
, m_pFiffInfo(QSharedPointer<FiffInfo>::create())
, m_pRMTSA_Natus(PluginOutputData<RealTimeMultiSampleArray>::create(this, "Natus", "EEG output data"))
, m_qStringResourcePath(qApp->applicationDirPath()+"/resources/mne_scan/plugins/natus/")
{
    m_pRMTSA_Natus->data()->setName(this->getName());//Provide name to auto store widget settings
}

//=============================================================================================================

Natus::~Natus()
{
    //If the program is closed while the sampling is in process
    if(this->isRunning()) {
        this->stop();
    }
}

//=============================================================================================================

QSharedPointer<IPlugin> Natus::clone() const
{
    QSharedPointer<Natus> pNatusClone(new Natus());
    return pNatusClone;
}

//=============================================================================================================

void Natus::init()
{
    m_outputConnectors.append(m_pRMTSA_Natus);
}

//=============================================================================================================

void Natus::unload()
{
}

//=============================================================================================================

void Natus::setUpFiffInfo()
{
    //Clear old fiff info data
    m_pFiffInfo->clear();

    //Set number of channels, sampling frequency and high/-lowpass
    m_pFiffInfo->nchan = m_iNumberChannels;
    m_pFiffInfo->sfreq = m_iSamplingFreq;
    m_pFiffInfo->highpass = 0.001f;
    m_pFiffInfo->lowpass = m_iSamplingFreq/2;

    //Set up the channel info
    QStringList QSLChNames;
    m_pFiffInfo->chs.clear();

    for(int i = 0; i < m_pFiffInfo->nchan; ++i)
    {
        //Create information for each channel
        QString sChType;
        FiffChInfo fChInfo;

//        //EEG Channels
//        if(i <= m_pFiffInfo->nchan-2)
//        {
            //Set channel name
            sChType = QString("EEG ");
            if(i<10) {
                sChType.append("00");
            }

            if(i>=10 && i<100) {
                sChType.append("0");
            }

            fChInfo.ch_name = sChType.append(sChType.number(i));

            //Set channel type
            fChInfo.kind = FIFFV_EEG_CH;

            //Set logno
            fChInfo.logNo = i;

            //Set coord frame
            fChInfo.coord_frame = FIFFV_COORD_HEAD;

            //Set unit
            fChInfo.unit = FIFF_UNIT_V;

            //Set EEG electrode location - Convert from mm to m
            fChInfo.eeg_loc(0,0) = 0;
            fChInfo.eeg_loc(1,0) = 0;
            fChInfo.eeg_loc(2,0) = 0;

            //Set EEG electrode direction - Convert from mm to m
            fChInfo.eeg_loc(0,1) = 0;
            fChInfo.eeg_loc(1,1) = 0;
            fChInfo.eeg_loc(2,1) = 0;

            //Also write the eeg electrode locations into the meg loc variable (mne_ex_read_raw() matlab function wants this)
            fChInfo.chpos.r0(0) = 0;
            fChInfo.chpos.r0(1) = 0;
            fChInfo.chpos.r0(2) = 0;

            fChInfo.chpos.ex(0) = 1;
            fChInfo.chpos.ex(1) = 0;
            fChInfo.chpos.ex(2) = 0;

            fChInfo.chpos.ey(0) = 0;
            fChInfo.chpos.ey(1) = 1;
            fChInfo.chpos.ey(2) = 0;

            fChInfo.chpos.ez(0) = 0;
            fChInfo.chpos.ez(1) = 0;
            fChInfo.chpos.ez(2) = 1;
//        }

//        //Digital input channel
//        if(i == m_pFiffInfo->nchan-1)
//        {
//            //Set channel type
//            fChInfo.kind = FIFFV_STIM_CH;

//            sChType = QString("STIM");
//            fChInfo.ch_name = sChType;
//        }

        QSLChNames << sChType;

        m_pFiffInfo->chs.append(fChInfo);
    }

    //Set channel names in fiff_info_base
    m_pFiffInfo->ch_names = QSLChNames;

    //Set head projection
    m_pFiffInfo->dev_head_t.from = FIFFV_COORD_DEVICE;
    m_pFiffInfo->dev_head_t.to = FIFFV_COORD_HEAD;
    m_pFiffInfo->ctf_head_t.from = FIFFV_COORD_DEVICE;
    m_pFiffInfo->ctf_head_t.to = FIFFV_COORD_HEAD;
}

//=============================================================================================================

bool Natus::start()
{
    // Init circular buffer to transmit data from the producer to this thread
    if(!m_pCircularBuffer) {
        m_pCircularBuffer = QSharedPointer<CircularBuffer_Matrix_double>(new CircularBuffer_Matrix_double(10));
    }

    //Setup fiff info before setting up the RMTSA because we need it to init the RTMSA
    setUpFiffInfo();

    //Set the channel size of the RMTSA - this needs to be done here and NOT in the init() function because the user can change the number of channels during runtime
    m_pRMTSA_Natus->data()->initFromFiffInfo(m_pFiffInfo);
    m_pRMTSA_Natus->data()->setMultiArraySize(1);

    QThread::start();

    // Start the producer
    m_pNatusProducer = QSharedPointer<NatusProducer>::create(m_iSamplesPerBlock, m_iNumberChannels);
    m_pNatusProducer->moveToThread(&m_pProducerThread);
    connect(m_pNatusProducer.data(), &NatusProducer::newDataAvailable,
            this, &Natus::onNewDataAvailable, Qt::DirectConnection);
    m_pProducerThread.start();

    return true;
}

//=============================================================================================================

bool Natus::stop()
{
    requestInterruption();
    wait(500);

    // Clear all data in the buffer connected to displays and other plugins
    m_pRMTSA_Natus->data()->clear();
    m_pCircularBuffer->clear();

    m_pProducerThread.quit();
    m_pProducerThread.wait();

    return true;
}

//=============================================================================================================

IPlugin::PluginType Natus::getType() const
{
    return _ISensor;
}

//=============================================================================================================

QString Natus::getName() const
{
    return "Natus EEG";
}

//=============================================================================================================

QWidget* Natus::setupWidget()
{
    NatusSetup* widget = new NatusSetup(this);//widget is later destroyed by CentralWidget - so it has to be created everytime new

    //init properties dialog
    widget->initGui();

    return widget;
}

//=============================================================================================================

void Natus::onNewDataAvailable(const Eigen::MatrixXd &matData)
{
    while(!m_pCircularBuffer->push(matData)) {
        //Do nothing until the circular buffer is ready to accept new data again
    }
}

//=============================================================================================================

void Natus::run()
{
    MatrixXd matData;

    while(!isInterruptionRequested()) {
        if(m_pCircularBuffer->pop(matData)) {
            //emit values
            if(!isInterruptionRequested()) {
                m_pRMTSA_Natus->data()->setValue(matData);
            }
        }
    }
}

<commit_msg>natus warnings<commit_after>//=============================================================================================================
/**
 * @file     natus.cpp
 * @author   Lorenz Esch <lesch@mgh.harvard.edu>
 * @version  dev
 * @date     June, 2018
 *
 * @section  LICENSE
 *
 * Copyright (C) 2018, Lorenz Esch. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided that
 * the following conditions are met:
 *     * Redistributions of source code must retain the above copyright notice, this list of conditions and the
 *       following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
 *       the following disclaimer in the documentation and/or other materials provided with the distribution.
 *     * Neither the name of MNE-CPP authors nor the names of its contributors may be used
 *       to endorse or promote products derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 *
 * @brief    Contains the definition of the Natus class.
 *
 */

//=============================================================================================================
// INCLUDES
//=============================================================================================================

#include "natus.h"
#include "natusproducer.h"
#include "FormFiles/natussetup.h"

#include <fiff/fiff.h>
#include <scMeas/realtimemultisamplearray.h>

//=============================================================================================================
// QT INCLUDES
//=============================================================================================================

#include <QSettings>

//=============================================================================================================
// EIGEN INCLUDES
//=============================================================================================================

//=============================================================================================================
// USED NAMESPACES
//=============================================================================================================

using namespace NATUSPLUGIN;
using namespace SCSHAREDLIB;
using namespace SCMEASLIB;
using namespace FIFFLIB;
using namespace Eigen;
using namespace IOBUFFER;

//=============================================================================================================
// DEFINE MEMBER METHODS
//=============================================================================================================

Natus::Natus()
: m_iSamplingFreq(2048)
, m_iNumberChannels(46)
, m_iSamplesPerBlock(256)
, m_qStringResourcePath(qApp->applicationDirPath()+"/resources/mne_scan/plugins/natus/")
, m_pRMTSA_Natus(PluginOutputData<RealTimeMultiSampleArray>::create(this, "Natus", "EEG output data"))
, m_pFiffInfo(QSharedPointer<FiffInfo>::create())
{
    m_pRMTSA_Natus->data()->setName(this->getName());//Provide name to auto store widget settings
}

//=============================================================================================================

Natus::~Natus()
{
    //If the program is closed while the sampling is in process
    if(this->isRunning()) {
        this->stop();
    }
}

//=============================================================================================================

QSharedPointer<IPlugin> Natus::clone() const
{
    QSharedPointer<IPlugin> pNatusClone(new Natus());
    return pNatusClone;
}

//=============================================================================================================

void Natus::init()
{
    m_outputConnectors.append(m_pRMTSA_Natus);
}

//=============================================================================================================

void Natus::unload()
{
}

//=============================================================================================================

void Natus::setUpFiffInfo()
{
    //Clear old fiff info data
    m_pFiffInfo->clear();

    //Set number of channels, sampling frequency and high/-lowpass
    m_pFiffInfo->nchan = m_iNumberChannels;
    m_pFiffInfo->sfreq = m_iSamplingFreq;
    m_pFiffInfo->highpass = 0.001f;
    m_pFiffInfo->lowpass = m_iSamplingFreq/2;

    //Set up the channel info
    QStringList QSLChNames;
    m_pFiffInfo->chs.clear();

    for(int i = 0; i < m_pFiffInfo->nchan; ++i)
    {
        //Create information for each channel
        QString sChType;
        FiffChInfo fChInfo;

//        //EEG Channels
//        if(i <= m_pFiffInfo->nchan-2)
//        {
            //Set channel name
            sChType = QString("EEG ");
            if(i<10) {
                sChType.append("00");
            }

            if(i>=10 && i<100) {
                sChType.append("0");
            }

            fChInfo.ch_name = sChType.append(sChType.number(i));

            //Set channel type
            fChInfo.kind = FIFFV_EEG_CH;

            //Set logno
            fChInfo.logNo = i;

            //Set coord frame
            fChInfo.coord_frame = FIFFV_COORD_HEAD;

            //Set unit
            fChInfo.unit = FIFF_UNIT_V;

            //Set EEG electrode location - Convert from mm to m
            fChInfo.eeg_loc(0,0) = 0;
            fChInfo.eeg_loc(1,0) = 0;
            fChInfo.eeg_loc(2,0) = 0;

            //Set EEG electrode direction - Convert from mm to m
            fChInfo.eeg_loc(0,1) = 0;
            fChInfo.eeg_loc(1,1) = 0;
            fChInfo.eeg_loc(2,1) = 0;

            //Also write the eeg electrode locations into the meg loc variable (mne_ex_read_raw() matlab function wants this)
            fChInfo.chpos.r0(0) = 0;
            fChInfo.chpos.r0(1) = 0;
            fChInfo.chpos.r0(2) = 0;

            fChInfo.chpos.ex(0) = 1;
            fChInfo.chpos.ex(1) = 0;
            fChInfo.chpos.ex(2) = 0;

            fChInfo.chpos.ey(0) = 0;
            fChInfo.chpos.ey(1) = 1;
            fChInfo.chpos.ey(2) = 0;

            fChInfo.chpos.ez(0) = 0;
            fChInfo.chpos.ez(1) = 0;
            fChInfo.chpos.ez(2) = 1;
//        }

//        //Digital input channel
//        if(i == m_pFiffInfo->nchan-1)
//        {
//            //Set channel type
//            fChInfo.kind = FIFFV_STIM_CH;

//            sChType = QString("STIM");
//            fChInfo.ch_name = sChType;
//        }

        QSLChNames << sChType;

        m_pFiffInfo->chs.append(fChInfo);
    }

    //Set channel names in fiff_info_base
    m_pFiffInfo->ch_names = QSLChNames;

    //Set head projection
    m_pFiffInfo->dev_head_t.from = FIFFV_COORD_DEVICE;
    m_pFiffInfo->dev_head_t.to = FIFFV_COORD_HEAD;
    m_pFiffInfo->ctf_head_t.from = FIFFV_COORD_DEVICE;
    m_pFiffInfo->ctf_head_t.to = FIFFV_COORD_HEAD;
}

//=============================================================================================================

bool Natus::start()
{
    // Init circular buffer to transmit data from the producer to this thread
    if(!m_pCircularBuffer) {
        m_pCircularBuffer = QSharedPointer<CircularBuffer_Matrix_double>(new CircularBuffer_Matrix_double(10));
    }

    //Setup fiff info before setting up the RMTSA because we need it to init the RTMSA
    setUpFiffInfo();

    //Set the channel size of the RMTSA - this needs to be done here and NOT in the init() function because the user can change the number of channels during runtime
    m_pRMTSA_Natus->data()->initFromFiffInfo(m_pFiffInfo);
    m_pRMTSA_Natus->data()->setMultiArraySize(1);

    QThread::start();

    // Start the producer
    m_pNatusProducer = QSharedPointer<NatusProducer>::create(m_iSamplesPerBlock, m_iNumberChannels);
    m_pNatusProducer->moveToThread(&m_pProducerThread);
    connect(m_pNatusProducer.data(), &NatusProducer::newDataAvailable,
            this, &Natus::onNewDataAvailable, Qt::DirectConnection);
    m_pProducerThread.start();

    return true;
}

//=============================================================================================================

bool Natus::stop()
{
    requestInterruption();
    wait(500);

    // Clear all data in the buffer connected to displays and other plugins
    m_pRMTSA_Natus->data()->clear();
    m_pCircularBuffer->clear();

    m_pProducerThread.quit();
    m_pProducerThread.wait();

    return true;
}

//=============================================================================================================

IPlugin::PluginType Natus::getType() const
{
    return _ISensor;
}

//=============================================================================================================

QString Natus::getName() const
{
    return "Natus EEG";
}

//=============================================================================================================

QWidget* Natus::setupWidget()
{
    NatusSetup* widget = new NatusSetup(this);//widget is later destroyed by CentralWidget - so it has to be created everytime new

    //init properties dialog
    widget->initGui();

    return widget;
}

//=============================================================================================================

void Natus::onNewDataAvailable(const Eigen::MatrixXd &matData)
{
    while(!m_pCircularBuffer->push(matData)) {
        //Do nothing until the circular buffer is ready to accept new data again
    }
}

//=============================================================================================================

void Natus::run()
{
    MatrixXd matData;

    while(!isInterruptionRequested()) {
        if(m_pCircularBuffer->pop(matData)) {
            //emit values
            if(!isInterruptionRequested()) {
                m_pRMTSA_Natus->data()->setValue(matData);
            }
        }
    }
}

<|endoftext|>