<commit_before>// This project underlies the optiMEAS Source Code License which is
// to be found at www.optimeas.de/source_code_license.

#pragma once

#include "scope_guard.hpp"
#include "task_queue_thread_pool.hpp"

#include <algorithm>
#include <cassert>
#include <future>
#include <map>
#include <type_traits>
#include <unordered_map>
#include <vector>

namespace cu
{

class DependencyThreadPoolBase
{
public:
  using Id = std::size_t;
  static constexpr const Id invalidId = ~static_cast<Id>(0);

  template <typename T>
  struct Result
  {
    Result() = default;

    Result( std::future<T> future_, Id id_ )
      : future( std::move(future_) )
      , id( id_ )
    {}

    std::future<T> future;
    Id id = invalidId;
  };
};

template <typename ...Args>
class DependencyThreadPool
    : public DependencyThreadPoolBase
{
public:
  template <typename F>
  decltype(auto) operator()(
      const std::initializer_list<Id> & dependencyIds,
      F && f )
  {
    return run( dependencyIds, std::forward<F>(f) );
  }

  template <typename F>
  decltype(auto) operator()(
      const std::vector<Id> & dependencyIds,
      F && f )
  {
    return run( dependencyIds, std::forward<F>(f) );
  }

private:
  template <typename F,
            typename IdContainer>
  Result<typename std::result_of<F(Args...)>::type> run(
      const IdContainer & dependencyIds,
      F && f )
  {
    auto pt = std::packaged_task<std::result_of_t<F(Args...)>(Args&&...)>(
          std::forward<F>(f) );
    auto future = pt.get_future();
    cu::MoveFunction<void(Args&&...)> task = std::move(pt);
    const auto id = data( [&]( Data & data )
    {
      const auto id = data.idCounter;
      ++data.idCounter;
      const auto nDependencies = data.updateDependencies( dependencyIds, id );
      data.nodes.insert(
        std::make_pair( id, Node{ nDependencies, {}, std::move(task) } ) );
      if ( nDependencies == 0 )
        queueTask( id, data.nodes );
      return id;
    } );
    return { std::move(future), id };
  }

  struct Node
  {
    Node(
        std::size_t nOpenDependencies_,
        std::vector<Id> dependentTasks_,
        cu::MoveFunction<void(Args&&...)> task_ )
      : nOpenDependencies( nOpenDependencies_ )
      , dependentTasks( std::move( dependentTasks_ ) )
      , task( std::move( task_ ) )
    {}

    std::size_t nOpenDependencies;
    std::vector<Id> dependentTasks;
    cu::MoveFunction<void(Args&&...)> task;
  };

  struct Data
  {
    Id idCounter = 0;
    std::map<Id,Node> nodes;

    template <typename IdContainer>
    std::size_t updateDependencies(
        const IdContainer & dependencies,
        Id id )
    {
      std::size_t nDependencies = 0;
      for ( auto dep : dependencies )
      {
        const auto it = nodes.find( dep );
        if ( it == nodes.end() )
          continue;
        it->second.dependentTasks.push_back( id );
        ++nDependencies;
      }
      return nDependencies;
    }
  };

  void queueTask( Id id, std::map<Id,Node> & nodes )
  {
    const auto nodeIt = nodes.find(id);
    assert( nodeIt != nodes.end() );
    assert( nodeIt->second.nOpenDependencies == 0 );
    workers( [this, nodeIt]
             ( Args &&... args ) mutable
    {
      CU_SCOPE_EXIT
      {
        this->data( [&]( Data & data )
        {
          for ( auto dependentId : nodeIt->second.dependentTasks )
          {
            const auto dependentNodeIt = data.nodes.find( dependentId );
            assert( dependentNodeIt != data.nodes.end() );
            const auto nRemainingDependencies =
                --dependentNodeIt->second.nOpenDependencies;
            if ( nRemainingDependencies == 0 )
              queueTask( dependentId, data.nodes );
          }
          data.nodes.erase( nodeIt );
        } );
      };
      nodeIt->second.task( std::forward<Args>(args)... );
    } );
  }

  cu::Monitor<Data> data;
  TaskQueueThreadPool<Args...> workers;
};

} // namespace cu
<commit_msg>The DependencyThreadPool works with cu::Slice arguments now.<commit_after>// This project underlies the optiMEAS Source Code License which is
// to be found at www.optimeas.de/source_code_license.

#pragma once

#include "scope_guard.hpp"
#include "slice.hpp"
#include "task_queue_thread_pool.hpp"

#include <algorithm>
#include <cassert>
#include <future>
#include <map>
#include <type_traits>
#include <unordered_map>

namespace cu
{

class DependencyThreadPoolBase
{
public:
  using Id = std::size_t;
  static constexpr const Id invalidId = ~static_cast<Id>(0);

  template <typename T>
  struct Result
  {
    Result() = default;

    Result( std::future<T> future_, Id id_ )
      : future( std::move(future_) )
      , id( id_ )
    {}

    std::future<T> future;
    Id id = invalidId;
  };
};

/// A threadpool for tasks that depend upon each other.
///
/// The threadpool will only start the execution of a task, if all the tasks
/// it depends on have been finished.
/// When the client issues a task, then an @c std::future<T> and a task id
/// will be returned in a @c DependencyThreadPoolBase::Result<T> structure.
/// The returned id can be used as dependency for other subsequent tasks.
/// Therefore cyclic dependencies are impossible by design.
///
/// The template type arguments are the arguments that will be passed to the
/// tasks and are data elements of the threadpool just as in
/// @c TaskQueueThreadPool.
template <typename ...Args>
class DependencyThreadPool
    : public DependencyThreadPoolBase
{
public:
  /// Schedules a task.
  ///
  /// The task will be executed only after all tasks it depends upon have
  /// been finished.
  /// @param dependencyIds specifies the tasks upon which the new task depends.
  /// @returns A struct with a member @c future which designates the
  /// asynchroneous result and a member @c id which identifies the task with a
  /// unique id. This id can be used as dependency id for new tasks.
  template <typename F>
  Result<typename std::result_of<F(Args...)>::type> operator()(
      const cu::Slice<const Id> dependencyIds,
      F && f )
  {
    auto pt = std::packaged_task<std::result_of_t<F(Args...)>(Args&&...)>(
          std::forward<F>(f) );
    auto future = pt.get_future();
    cu::MoveFunction<void(Args&&...)> task = std::move(pt);
    const auto id = data( [&]( Data & data )
    {
      const auto id = data.idCounter;
      ++data.idCounter;
      const auto nDependencies = data.updateDependencies( dependencyIds, id );
      data.nodes.insert(
        std::make_pair( id, Node{ nDependencies, {}, std::move(task) } ) );
      if ( nDependencies == 0 )
        queueTask( id, data.nodes );
      return id;
    } );
    return { std::move(future), id };
  }

private:
  struct Node
  {
    Node(
        std::size_t nOpenDependencies_,
        std::vector<Id> dependentTasks_,
        cu::MoveFunction<void(Args&&...)> task_ )
      : nOpenDependencies( nOpenDependencies_ )
      , dependentTasks( std::move( dependentTasks_ ) )
      , task( std::move( task_ ) )
    {}

    std::size_t nOpenDependencies;
    std::vector<Id> dependentTasks;
    cu::MoveFunction<void(Args&&...)> task;
  };

  struct Data
  {
    Id idCounter = 0;
    std::map<Id,Node> nodes;

    std::size_t updateDependencies(
        const cu::Slice<const Id>  dependencies,
        Id id )
    {
      std::size_t nDependencies = 0;
      for ( auto dep : dependencies )
      {
        const auto it = nodes.find( dep );
        if ( it == nodes.end() )
          continue;
        it->second.dependentTasks.push_back( id );
        ++nDependencies;
      }
      return nDependencies;
    }
  };

  void queueTask( Id id, std::map<Id,Node> & nodes )
  {
    const auto nodeIt = nodes.find(id);
    assert( nodeIt != nodes.end() );
    assert( nodeIt->second.nOpenDependencies == 0 );
    workers( [this, nodeIt]
             ( Args &&... args ) mutable
    {
      CU_SCOPE_EXIT
      {
        this->data( [&]( Data & data )
        {
          for ( auto dependentId : nodeIt->second.dependentTasks )
          {
            const auto dependentNodeIt = data.nodes.find( dependentId );
            assert( dependentNodeIt != data.nodes.end() );
            const auto nRemainingDependencies =
                --dependentNodeIt->second.nOpenDependencies;
            if ( nRemainingDependencies == 0 )
              queueTask( dependentId, data.nodes );
          }
          data.nodes.erase( nodeIt );
        } );
      };
      nodeIt->second.task( std::forward<Args>(args)... );
    } );
  }

  cu::Monitor<Data> data;
  TaskQueueThreadPool<Args...> workers;
};

} // namespace cu
<|endoftext|>


<commit_before><commit_msg>Eagerly initialize NSS and OCSP on IOThread.<commit_after><|endoftext|>


<commit_before>/*
*
* Copyright (C) 2004 Mekensleep
*
*    Mekensleep
*    24 rue vieille du temple
*    75004 Paris
*       licensing@mekensleep.com
*
* 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
*
* Author:
*  Igor Kravtchenko <igor@obraz.net>
*
*/

#include "hdrloader.h"

#include <math.h>
#include <memory.h>
#include <stdio.h>

typedef unsigned char RGBE[4];
#define R            0
#define G            1
#define B            2
#define E            3

#define  MINELEN    8                // minimum scanline length for encoding
#define  MAXELEN    0x7fff            // maximum scanline length for encoding

static void workOnRGBE(RGBE *scan, int len, float *cols);
static bool decrunch(RGBE *scanline, int len, FILE *file);
static bool oldDecrunch(RGBE *scanline, int len, FILE *file);

bool HDRLoader::isHDRFile(const char *_fileName)
{
    FILE *file;
    file = fopen(_fileName, "rb");
    if (!file)
        return false;

    char str[10];
    fread(str, 10, 1, file);
    fclose(file);

    if (memcmp(str, "#?RADIANCE", 10) && memcmp(str, "#?RGBE", 6))
        return false;

    return true;
}

bool HDRLoader::load(const char *_fileName, HDRLoaderResult &_res)
{
    int i;
    char str[200];
    FILE *file;

    file = fopen(_fileName, "rb");
    if (!file)
        return false;

    fread(str, 10, 1, file);
    if (memcmp(str, "#?RADIANCE", 10)) {
        fseek(file, 0, SEEK_SET);
        fread(str, 6, 1, file);
        if (memcmp(str, "#?RGBE", 6)) {
            fclose(file);
            return false;
        }
    }
    fseek(file, 1, SEEK_CUR);

    char cmd[2000];
    i = 0;
    char c = 0, oldc;
    while(true) {
        oldc = c;
        c = fgetc(file);
        if (c == 0xa && oldc == 0xa)
            break;
        cmd[i++] = c;
    }

    char reso[2000];
    i = 0;
    while(true) {
        c = fgetc(file);
        reso[i++] = c;
        if (c == 0xa)
            break;
    }

    int w, h;
    if (!sscanf(reso, "-Y %d +X %d", &h, &w)) {
        fclose(file);
        return false;
    }

    _res.width = w;
    _res.height = h;

    float *cols = new float[w * h * 3];
    _res.cols = cols;

    RGBE *scanline = new RGBE[w];
    if (!scanline) {
        fclose(file);
        return false;
    }

    // convert image
    cols += (h-1) * w * 3;
    for (int y = h - 1; y >= 0; y--) {
        if (decrunch(scanline, w, file) == false)
            break;
        workOnRGBE(scanline, w, cols);
        cols -= w * 3;
    }

    delete [] scanline;
    fclose(file);

    return true;
}

float convertComponent(int _expo, int _val)
{
    float v = _val / 256.0f;
    float d = powf(2.0f, (float)_expo);
    return v * d;
}

void workOnRGBE(RGBE *_scan, int _len, float *_cols)
{
    int ii = 0;
    while (_len-- > 0) {
        int expo = _scan[0][E] - 128;
        _cols[0] = convertComponent(expo, _scan[0][R]);
        _cols[1] = convertComponent(expo, _scan[0][G]);
        _cols[2] = convertComponent(expo, _scan[0][B]);
        _cols += 3;
        _scan++;
        ii++;
    }
}

bool decrunch(RGBE *_scanline, int _len, FILE *_file)
{
    int  i, j;

    if (_len < MINELEN || _len > MAXELEN)
        return oldDecrunch(_scanline, _len, _file);

    i = fgetc(_file);
    if (i != 2) {
        fseek(_file, -1, SEEK_CUR);
        return oldDecrunch(_scanline, _len, _file);
    }

    _scanline[0][G] = fgetc(_file);
    _scanline[0][B] = fgetc(_file);
    i = fgetc(_file);

    if (_scanline[0][G] != 2 || _scanline[0][B] & 128) {
        _scanline[0][R] = 2;
        _scanline[0][E] = i;
        return oldDecrunch(_scanline + 1, _len - 1, _file);
    }

    // read each component
    for (i = 0; i < 4; i++) {
        for (j = 0; j < _len; ) {
            unsigned char code = fgetc(_file);
            if (code > 128) { // run
                code &= 127;
                unsigned char val = fgetc(_file);
                while (code--)
                    _scanline[j++][i] = val;
            }
            else  {    // non-run
                while(code--)
                    _scanline[j++][i] = fgetc(_file);
            }
        }
    }

    return feof(_file) ? false : true;
}

bool oldDecrunch(RGBE *_scanline, int _len, FILE *_file)
{
    int i;
    int rshift = 0;

    while (_len > 0) {
        _scanline[0][R] = fgetc(_file);
        _scanline[0][G] = fgetc(_file);
        _scanline[0][B] = fgetc(_file);
        _scanline[0][E] = fgetc(_file);
        if (feof(_file))
            return false;

        if (_scanline[0][R] == 1 &&
            _scanline[0][G] == 1 &&
            _scanline[0][B] == 1) {
                for (i = _scanline[0][E] << rshift; i > 0; i--) {
                    memcpy(&_scanline[0][0], &_scanline[-1][0], 4);
                    _scanline++;
                    _len--;
                }
                rshift += 8;
            }
        else {
            _scanline++;
            _len--;
            rshift = 0;
        }
    }
    return true;
}
<commit_msg>From Olaf Flebbe, change from powf to ldexp.<commit_after>/*
*
* Copyright (C) 2004 Mekensleep
*
*    Mekensleep
*    24 rue vieille du temple
*    75004 Paris
*       licensing@mekensleep.com
*
* 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
*
* Author:
*  Igor Kravtchenko <igor@obraz.net>
*
*/

#include "hdrloader.h"

#include <math.h>
#include <memory.h>
#include <stdio.h>

typedef unsigned char RGBE[4];
#define R            0
#define G            1
#define B            2
#define E            3

#define  MINELEN    8                // minimum scanline length for encoding
#define  MAXELEN    0x7fff            // maximum scanline length for encoding

static void workOnRGBE(RGBE *scan, int len, float *cols);
static bool decrunch(RGBE *scanline, int len, FILE *file);
static bool oldDecrunch(RGBE *scanline, int len, FILE *file);

bool HDRLoader::isHDRFile(const char *_fileName)
{
    FILE *file;
    file = fopen(_fileName, "rb");
    if (!file)
        return false;

    char str[10];
    fread(str, 10, 1, file);
    fclose(file);

    if (memcmp(str, "#?RADIANCE", 10) && memcmp(str, "#?RGBE", 6))
        return false;

    return true;
}

bool HDRLoader::load(const char *_fileName, HDRLoaderResult &_res)
{
    int i;
    char str[200];
    FILE *file;

    file = fopen(_fileName, "rb");
    if (!file)
        return false;

    fread(str, 10, 1, file);
    if (memcmp(str, "#?RADIANCE", 10)) {
        fseek(file, 0, SEEK_SET);
        fread(str, 6, 1, file);
        if (memcmp(str, "#?RGBE", 6)) {
            fclose(file);
            return false;
        }
    }
    fseek(file, 1, SEEK_CUR);

    char cmd[2000];
    i = 0;
    char c = 0, oldc;
    while(true) {
        oldc = c;
        c = fgetc(file);
        if (c == 0xa && oldc == 0xa)
            break;
        cmd[i++] = c;
    }

    char reso[2000];
    i = 0;
    while(true) {
        c = fgetc(file);
        reso[i++] = c;
        if (c == 0xa)
            break;
    }

    int w, h;
    if (!sscanf(reso, "-Y %d +X %d", &h, &w)) {
        fclose(file);
        return false;
    }

    _res.width = w;
    _res.height = h;

    float *cols = new float[w * h * 3];
    _res.cols = cols;

    RGBE *scanline = new RGBE[w];
    if (!scanline) {
        fclose(file);
        return false;
    }

    // convert image
    cols += (h-1) * w * 3;
    for (int y = h - 1; y >= 0; y--) {
        if (decrunch(scanline, w, file) == false)
            break;
        workOnRGBE(scanline, w, cols);
        cols -= w * 3;
    }

    delete [] scanline;
    fclose(file);

    return true;
}

float convertComponent(int _expo, int _val)
{
    return ldexp( (float)_val / 256.0f, _expo);
}

void workOnRGBE(RGBE *_scan, int _len, float *_cols)
{
    int ii = 0;
    while (_len-- > 0) {
        int expo = _scan[0][E] - 128;
        _cols[0] = convertComponent(expo, _scan[0][R]);
        _cols[1] = convertComponent(expo, _scan[0][G]);
        _cols[2] = convertComponent(expo, _scan[0][B]);
        _cols += 3;
        _scan++;
        ii++;
    }
}

bool decrunch(RGBE *_scanline, int _len, FILE *_file)
{
    int  i, j;

    if (_len < MINELEN || _len > MAXELEN)
        return oldDecrunch(_scanline, _len, _file);

    i = fgetc(_file);
    if (i != 2) {
        fseek(_file, -1, SEEK_CUR);
        return oldDecrunch(_scanline, _len, _file);
    }

    _scanline[0][G] = fgetc(_file);
    _scanline[0][B] = fgetc(_file);
    i = fgetc(_file);

    if (_scanline[0][G] != 2 || _scanline[0][B] & 128) {
        _scanline[0][R] = 2;
        _scanline[0][E] = i;
        return oldDecrunch(_scanline + 1, _len - 1, _file);
    }

    // read each component
    for (i = 0; i < 4; i++) {
        for (j = 0; j < _len; ) {
            unsigned char code = fgetc(_file);
            if (code > 128) { // run
                code &= 127;
                unsigned char val = fgetc(_file);
                while (code--)
                    _scanline[j++][i] = val;
            }
            else  {    // non-run
                while(code--)
                    _scanline[j++][i] = fgetc(_file);
            }
        }
    }

    return feof(_file) ? false : true;
}

bool oldDecrunch(RGBE *_scanline, int _len, FILE *_file)
{
    int i;
    int rshift = 0;

    while (_len > 0) {
        _scanline[0][R] = fgetc(_file);
        _scanline[0][G] = fgetc(_file);
        _scanline[0][B] = fgetc(_file);
        _scanline[0][E] = fgetc(_file);
        if (feof(_file))
            return false;

        if (_scanline[0][R] == 1 &&
            _scanline[0][G] == 1 &&
            _scanline[0][B] == 1) {
                for (i = _scanline[0][E] << rshift; i > 0; i--) {
                    memcpy(&_scanline[0][0], &_scanline[-1][0], 4);
                    _scanline++;
                    _len--;
                }
                rshift += 8;
            }
        else {
            _scanline++;
            _len--;
            rshift = 0;
        }
    }
    return true;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015 - 2018 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include "defines.hpp"
#include "types.hpp"

#if defined(_MSC_VER)
#include <malloc.h>
#define ox_alloca(size) _alloca(size)
#elif OX_USE_STDLIB
#include <stdlib.h>
#define ox_alloca(size) alloca(size)
#else
#define ox_alloca(size) __builtin_alloca(size)
#endif

void *operator new(std::size_t, void*) noexcept;

/**
 * @return an ox::MallocaPtr of the given type pointing to the requested size memory allocation
 */
#if defined(OX_USE_STDLIB)
#define ox_malloca(size, Type, ...) ox::MallocaPtr<Type>(size > ox::MallocaStackLimit, new (size > ox::MallocaStackLimit ? new uint8_t[size] : ox_alloca(size)) Type(__VA_ARGS__))
#else
#define ox_malloca(size, Type, ...) ox::MallocaPtr<Type>(false, new (ox_alloca(size)) Type(__VA_ARGS__))
#endif

namespace ox {

constexpr auto MallocaStackLimit = ox::defines::UseStdLib ? 1024 : 0;

/**
 * MallocaPtr will automatically cleanup the pointed to address upon
 * destruction if the size of the allocation is greater than MallocaStackLimit.
 */
template<typename T>
class MallocaPtr {

	private:
		bool m_onHeap = false;
		T *m_val = nullptr;

	public:
		inline MallocaPtr() noexcept = default;

		inline MallocaPtr(MallocaPtr &other) = delete;

		inline MallocaPtr(const MallocaPtr &other) = delete;

		inline MallocaPtr(MallocaPtr &&other) noexcept {
			m_onHeap = other.m_onHeap;
			m_val = other.m_val;
			other.m_onHeap = false;
			other.m_val = nullptr;
		}

		inline MallocaPtr(bool onHeap, T *val) noexcept {
			m_onHeap = onHeap;
			m_val = val;
		}

		inline ~MallocaPtr() noexcept {
			if (m_onHeap && m_val) {
				delete[] reinterpret_cast<uint8_t*>(m_val);
			}
		}

		inline const T *get() const noexcept {
			return reinterpret_cast<T*>(m_val);
		}

		inline T *get() noexcept {
			return reinterpret_cast<T*>(m_val);
		}

		inline const T &operator=(MallocaPtr &other) = delete;

		inline const T &operator=(const MallocaPtr &other) = delete;

		inline const T &operator=(MallocaPtr &&other) noexcept {
			if (m_onHeap && m_val) {
				delete[] reinterpret_cast<uint8_t*>(m_val);
			}
			m_onHeap = other.m_onHeap;
			m_val = other.m_val;
			other.m_onHeap = false;
			other.m_val = nullptr;
		}

		inline const T *operator->() const noexcept {
			return reinterpret_cast<T*>(m_val);
		}

		inline T *operator->() noexcept {
			return reinterpret_cast<T*>(m_val);
		}

		inline operator const T*() const noexcept {
			return reinterpret_cast<T*>(m_val);
		}

		inline operator T*() noexcept {
			return reinterpret_cast<T*>(m_val);
		}

		inline const T &operator*() const noexcept {
			return *reinterpret_cast<T*>(m_val);
		}

		inline T &operator*() noexcept {
			return *reinterpret_cast<T*>(m_val);
		}

		inline bool operator==(const MallocaPtr<T> &other) const noexcept {
			return m_val == other.m_val && m_onHeap == other.m_onHeap;
		}

		inline bool operator!=(const MallocaPtr<T> &other) const noexcept {
			return m_val != other.m_val || m_onHeap != other.m_onHeap;
		}

};

}
<commit_msg>[ox/std] Fix placement new declaration to use stdlib declaration if available<commit_after>/*
 * Copyright 2015 - 2018 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include "defines.hpp"
#include "types.hpp"

#if defined(_MSC_VER)
#include <malloc.h>
#define ox_alloca(size) _alloca(size)
#elif OX_USE_STDLIB
#include <stdlib.h>
#define ox_alloca(size) alloca(size)
#else
#define ox_alloca(size) __builtin_alloca(size)
#endif

#if __has_include(<new>)
#include <new>
#else
void *operator new(std::size_t, void*) noexcept;
#endif

/**
 * @return an ox::MallocaPtr of the given type pointing to the requested size memory allocation
 */
#if defined(OX_USE_STDLIB)
#define ox_malloca(size, Type, ...) ox::MallocaPtr<Type>(size > ox::MallocaStackLimit, new (size > ox::MallocaStackLimit ? new uint8_t[size] : ox_alloca(size)) Type(__VA_ARGS__))
#else
#define ox_malloca(size, Type, ...) ox::MallocaPtr<Type>(false, new (ox_alloca(size)) Type(__VA_ARGS__))
#endif

namespace ox {

constexpr auto MallocaStackLimit = ox::defines::UseStdLib ? 1024 : 0;

/**
 * MallocaPtr will automatically cleanup the pointed to address upon
 * destruction if the size of the allocation is greater than MallocaStackLimit.
 */
template<typename T>
class MallocaPtr {

	private:
		bool m_onHeap = false;
		T *m_val = nullptr;

	public:
		inline MallocaPtr() noexcept = default;

		inline MallocaPtr(MallocaPtr &other) = delete;

		inline MallocaPtr(const MallocaPtr &other) = delete;

		inline MallocaPtr(MallocaPtr &&other) noexcept {
			m_onHeap = other.m_onHeap;
			m_val = other.m_val;
			other.m_onHeap = false;
			other.m_val = nullptr;
		}

		inline MallocaPtr(bool onHeap, T *val) noexcept {
			m_onHeap = onHeap;
			m_val = val;
		}

		inline ~MallocaPtr() noexcept {
			if (m_onHeap && m_val) {
				delete[] reinterpret_cast<uint8_t*>(m_val);
			}
		}

		inline const T *get() const noexcept {
			return reinterpret_cast<T*>(m_val);
		}

		inline T *get() noexcept {
			return reinterpret_cast<T*>(m_val);
		}

		inline const T &operator=(MallocaPtr &other) = delete;

		inline const T &operator=(const MallocaPtr &other) = delete;

		inline const T &operator=(MallocaPtr &&other) noexcept {
			if (m_onHeap && m_val) {
				delete[] reinterpret_cast<uint8_t*>(m_val);
			}
			m_onHeap = other.m_onHeap;
			m_val = other.m_val;
			other.m_onHeap = false;
			other.m_val = nullptr;
		}

		inline const T *operator->() const noexcept {
			return reinterpret_cast<T*>(m_val);
		}

		inline T *operator->() noexcept {
			return reinterpret_cast<T*>(m_val);
		}

		inline operator const T*() const noexcept {
			return reinterpret_cast<T*>(m_val);
		}

		inline operator T*() noexcept {
			return reinterpret_cast<T*>(m_val);
		}

		inline const T &operator*() const noexcept {
			return *reinterpret_cast<T*>(m_val);
		}

		inline T &operator*() noexcept {
			return *reinterpret_cast<T*>(m_val);
		}

		inline bool operator==(const MallocaPtr<T> &other) const noexcept {
			return m_val == other.m_val && m_onHeap == other.m_onHeap;
		}

		inline bool operator!=(const MallocaPtr<T> &other) const noexcept {
			return m_val != other.m_val || m_onHeap != other.m_onHeap;
		}

};

}
<|endoftext|>


<commit_before>/**
 *       \file  jacobian.cpp
 *      \brief  Implementation of Jacobian Matrix
 *     \author  Nikonov Max
 *       \date  27.06.2008
 *  \copyright  This source code is released under the terms of
 *              the BSD License. See LICENSE for more details.
 * */
#include "stdafx.h"
#include "jacobian.h"

namespace blue_sky
  {

  /**
   * \class jacob_traits
   * \brief For sorting jacobian children
   * */
  struct jacob_traits : bs_node::sort_traits
    {
      struct jacob_key : bs_node::sort_traits::key_type
        {
          virtual bool sort_order (const key_ptr & ) const
            {
              return true;
            }
        };

      virtual const char * sort_name () const
        {
          return "jacob trait";
        };

      virtual key_ptr key_generator (const sp_link& /*l*/) const
        {
          return new jacob_key ();
        }

      virtual bool accepts (const sp_link& l)
      {
        return smart_ptr< jacobian, true >(l->data(), bs_dynamic_cast());
      }
    };

  jacobian::~jacobian ()
  {
  }

  /**
   * \brief  'default' ctor for jacobian
   * \param  param Additional params for ctor
   * */
  jacobian::jacobian (bs_type_ctor_param /*param*/)
  : bs_node(bs_node::create_node(new jacob_traits))
  {
  }

  /**
   * \brief  copy-ctor for jacobian
   * \param  src Instance of jacobian to be copied
   * */
  jacobian::jacobian (const jacobian& src)
  : bs_refcounter (src), bs_node(src)
  {
    *this = src;
  }

  void
  jacobian::setup_solver (const BS_SP (fi_params) &ts_params)
  {
    solver->get_prop()->set_i (max_iters_idx, ts_params->get_int(fi_params::LIN_ITERS_NUM));
    solver->get_prop()->set_f (tol_idx, ts_params->get_float(fi_params::LIN_SOLV_RESIDUAL));
    //solver->get_prop()->set_matbal_tolerance(ts_params->get_float(fi_params::LIN_SOLV_MATBAL_RESIDUAL));
  }

  void
  jacobian::setup_preconditioner (const BS_SP (fi_params) &ts_params)
  {
//    //set up preconditioner
//    if (prec_is_cpr_flag)
//      {
//#ifdef _MPI
//        BS_ASSERT (false && "MPI: NOT IMPL YET");
//        smart_ptr< /*!mpi_*/cpr_preconditioner<strategy_t> > cpr = ((static_cast< smart_ptr< two_stage_preconditioner<strategy_t> > >(preconditioner))->get_prec_1());
//#else // _MPI
//        smart_ptr< cpr_preconditioner<strategy_t> > cpr = ((static_cast< smart_ptr< two_stage_preconditioner<strategy_t> > >(preconditioner))->get_prec_1());
//#endif // _MPI
//
//        BS_ASSERT (cpr);
//        BS_ASSERT (cpr->get_prop ());
//
//        cpr->get_prop()->set_max_iters(ts_params->get_int(fi_params::AMG_LIN_ITERS_NUM));
//        cpr->get_prop()->set_matbal_tolerance(ts_params->get_float(fi_params::AMG_RESID));
//      }
  }

  int
  jacobian::setup_solver_params (well_model_type model_type, int n_phases, const BS_SP (fi_params) &ts_params)
  {

    if (!ts_params)
      {
        throw bs_exception("Jacobian::setup_solver_params", "ts_params is not inited!");
      }

    if (!solver)
      {
        bs_throw_exception ("Solver is null");
      }
    if (!preconditioner)
      {
        bs_throw_exception ("Preconditioner is null");
      }

    if (solver_is_gmres_flag)
      {
        solver->get_prop ()->set_i (ortonorm_vlen, ts_params->get_int (fi_params::GMRES_ORTONORM_VLEN));
        //static_cast< smart_ptr< gmres_solver2<strategy_t> > >(solver)->m
        //= ts_params->get_int(fi_params::GMRES_ORTONORM_VLEN);
      }

    setup_solver (ts_params);
    setup_preconditioner (ts_params);

    solver->set_prec(preconditioner);
    return 0;
  }

  const BS_SP (lsolver_iface) &
  jacobian::get_solver () const
  {
    return solver;
  }

  const BS_SP (lsolver_iface) &
  jacobian::get_prec () const
  {
    return preconditioner;
  }

  void
  jacobian::init (t_long elements, t_long phases_, t_long secondary_)
  {
    secondary = secondary_;
    phases = phases_;

    matrix = BS_KERNEL.create_object ("mbcsr_matrix");
    flux_conn = BS_KERNEL.create_object ("flux_connections");

    BS_SP (bcsr_matrix_iface) flux = BS_KERNEL.create_object ("bcsr_matrix");
    BS_SP (bcsr_matrix_iface) facility = BS_KERNEL.create_object ("bcsr_matrix");
    BS_SP (bcsr_matrix_iface) accum = BS_KERNEL.create_object ("bcsr_matrix");

    matrix->add_matrix ("flux", flux);
    matrix->add_matrix ("facility", facility);
    matrix->add_matrix ("accum", accum);

    facility->alloc_rows_ptr (elements);

    accum->init (elements, elements, phases, elements);
    t_long *accum_rows = accum->get_rows_ptr ()->data ();
    t_long *accum_cols = accum->get_cols_ind ()->data ();
    t_double *accum_vals = accum->get_values ()->data ();
    // OPENMP
    for (t_long i = 0; i < elements; ++i)
      {
        accum_rows[i] = i;
        accum_cols[i] = i;
      }
    for (t_long i = 0; i < elements * phases; ++i)
      {
        accum_vals[i] = 0;
      }

    rhs = BS_KERNEL.create_object (v_float::bs_type ());
    rhs_flux = BS_KERNEL.create_object (v_float::bs_type ());
    sec_rhs = BS_KERNEL.create_object (v_float::bs_type ());
    ss_diagonal = BS_KERNEL.create_object (v_float::bs_type ());
    sp_diagonal = BS_KERNEL.create_object (v_float::bs_type ());

    cfl_vector = BS_KERNEL.create_object (v_double::bs_type ());
    solution = BS_KERNEL.create_object (v_double::bs_type ());
    sec_solution = BS_KERNEL.create_object (v_double::bs_type ());

    boundary = BS_KERNEL.create_object (v_long::bs_type ());

    rhs->init (elements * phases, 0);
    rhs_flux->init (elements * phases, 0);
    cfl_vector->init (elements * phases, 0);
    solution->init (elements * phases, 0);

    if (secondary > 0)
      {
        sec_rhs->init (secondary * elements, 0);
        ss_diagonal->init (secondary * secondary * elements, 0);
        sp_diagonal->init (secondary * elements * phases, 0);
        sec_solution->init (secondary * elements, 0);
      }
    else
      {
        sec_rhs->init (1, 0);
        ss_diagonal->init (1, 0);
        sp_diagonal->init (1, 0);
        sec_solution->init (1, 0);
      }

    // FIXME: copied from reservoir_simulator
    //index_t N_block_size = cm->n_phases;
    //index_t N_blocks = hdm->get_mesh ()->get_n_active_elements ();
    //// FIXME: wrong init?
    //jmatrix->get_flux_matrix()->get_values ()->init (N_block_size, 0);
    //jmatrix->get_flux_matrix ()->get_values()->init (N_block_size * N_block_size * (2* hdm->get_mesh ()->get_n_connections() + hdm->get_mesh ()->get_n_active_elements()), item_t (0));

    //jmatrix->get_facility_matrix ()->init (N_blocks, N_blocks, N_block_size, 0);
  }

  BS_SP (bcsr_matrix_iface)
  jacobian::get_matrix (std::string const &name) const
  {
    BS_ASSERT (matrix);
    if (name == "trns")
      return flux_conn->get_conn_trans ();

    return matrix->get_matrix (name);
  }

  BS_SP (mbcsr_matrix_iface)
  jacobian::get_matrix () const
  {
    BS_ASSERT (matrix);
    return matrix;
  }

  spv_float
  jacobian::get_ss_diagonal ()
  {
    return ss_diagonal;
  }

  spv_float
  jacobian::get_sp_diagonal ()
  {
    return sp_diagonal;
  }

  spv_float
  jacobian::get_sec_rhs ()
  {
    return sec_rhs;
  }

  spv_float
  jacobian::get_rhs ()
  {
    return rhs;
  }

  spv_float
  jacobian::get_rhs_flux ()
  {
    return rhs_flux;
  }

  spv_float
  jacobian::get_cfl_vector ()
  {
    return cfl_vector;
  }

  spv_double
  jacobian::get_solution ()
  {
    return solution;
  }

  spv_double
  jacobian::get_sec_solution ()
  {
    return sec_solution;
  }

  spv_long
  jacobian::get_boundary ()
  {
    return boundary;
  }

  BS_SP (flux_connections_iface)
  jacobian::get_flux_connections ()
  {
    return flux_conn;
  }

  spv_long
  jacobian::get_m_array ()
  {
    BS_ASSERT (flux_conn);
    return flux_conn->get_matrix_block_idx_minus ();
  }

  spv_long
  jacobian::get_p_array ()
  {
    BS_ASSERT (flux_conn);
    return flux_conn->get_matrix_block_idx_plus ();
  }

  // FIXME:
  void
  jacobian::clear_solution ()
  {
    solution->assign (0);
  }

  // FIXME:
  void
  jacobian::summ_rhs ()
  {
    if (rhs->size () != rhs_flux->size ())
      {
        bs_throw_exception ("rhs and rhs_flux size mismatch");
      }

    t_float *rhs_ = rhs->data ();
    t_float *rhs_flux_ = rhs_flux->data ();

    // OPENMP:
    for (size_t i = 0, cnt = rhs->size (); i < cnt; ++i)
      {
        rhs_[i] += rhs_flux_[i];
      }
  }

  // FIXME:
  void
  jacobian::mult_flux_part (t_double mult)
  {
    spv_double facility = matrix->get_matrix ("facility")->get_values ();
    spv_double flux     = matrix->get_matrix ("flux")->get_values ();
    t_double *facility_ = facility->data ();
    t_double *flux_     = flux->data ();
    t_float *rhs_flux_  = rhs_flux->data ();

    // FIXME: should we multiply facility?
    // OPENMP
    for (size_t i = 0, cnt = facility->size (); i < cnt; ++i)
      {
        facility_[i] *= mult;
      }
    for (size_t i = 0, cnt = flux->size (); i < cnt; ++i)
      {
        flux_[i] *= mult;
      }
    for (size_t i = 0, cnt = rhs_flux->size (); i < cnt; ++i)
      {
        rhs_flux_[i] *= mult;
      }
  }

  // FIXME:
  void
  jacobian::restore_sec_solution ()
  {
    if (secondary > 0)
      {
        if (phases != matrix->get_matrix ("flux")->get_n_block_size ())
          {
            bs_throw_exception ("phases and flux block_size mismatch");
          }

        spv_long rows     = matrix->get_matrix ("flux")->get_rows_ptr ();
        t_float *sp_diag  = sp_diagonal->data ();
        t_double *sol     = solution->data ();
        t_double *sec_sol = sec_solution->data ();
        t_float *sec_rhs_ = sec_rhs->data ();

        // OPENMP
        for (t_long i = 0, cnt = (t_long)rows->size (); i < cnt - 1; ++i)
          {
            t_float *sp_block   = &sp_diag[secondary * phases * i];
            t_double *sol_block = &sol[phases * i];
            sec_sol[i]          = sec_rhs_[i];

            VV_PROD_M (phases, sp_block, sol_block, sec_sol[i]);
          }
      }
  }

  BLUE_SKY_TYPE_STD_CREATE (jacobian);
  BLUE_SKY_TYPE_STD_COPY (jacobian);

  BLUE_SKY_TYPE_IMPL (jacobian, bs_node, "jacobian", "Jacobian", "Jacobian");
};

<commit_msg>Fix rows initialization of accum matrix<commit_after>/**
 *       \file  jacobian.cpp
 *      \brief  Implementation of Jacobian Matrix
 *     \author  Nikonov Max
 *       \date  27.06.2008
 *  \copyright  This source code is released under the terms of
 *              the BSD License. See LICENSE for more details.
 * */
#include "stdafx.h"
#include "jacobian.h"

namespace blue_sky
  {

  /**
   * \class jacob_traits
   * \brief For sorting jacobian children
   * */
  struct jacob_traits : bs_node::sort_traits
    {
      struct jacob_key : bs_node::sort_traits::key_type
        {
          virtual bool sort_order (const key_ptr & ) const
            {
              return true;
            }
        };

      virtual const char * sort_name () const
        {
          return "jacob trait";
        };

      virtual key_ptr key_generator (const sp_link& /*l*/) const
        {
          return new jacob_key ();
        }

      virtual bool accepts (const sp_link& l)
      {
        return smart_ptr< jacobian, true >(l->data(), bs_dynamic_cast());
      }
    };

  jacobian::~jacobian ()
  {
  }

  /**
   * \brief  'default' ctor for jacobian
   * \param  param Additional params for ctor
   * */
  jacobian::jacobian (bs_type_ctor_param /*param*/)
  : bs_node(bs_node::create_node(new jacob_traits))
  {
  }

  /**
   * \brief  copy-ctor for jacobian
   * \param  src Instance of jacobian to be copied
   * */
  jacobian::jacobian (const jacobian& src)
  : bs_refcounter (src), bs_node(src)
  {
    *this = src;
  }

  void
  jacobian::setup_solver (const BS_SP (fi_params) &ts_params)
  {
    solver->get_prop()->set_i (max_iters_idx, ts_params->get_int(fi_params::LIN_ITERS_NUM));
    solver->get_prop()->set_f (tol_idx, ts_params->get_float(fi_params::LIN_SOLV_RESIDUAL));
    //solver->get_prop()->set_matbal_tolerance(ts_params->get_float(fi_params::LIN_SOLV_MATBAL_RESIDUAL));
  }

  void
  jacobian::setup_preconditioner (const BS_SP (fi_params) &ts_params)
  {
//    //set up preconditioner
//    if (prec_is_cpr_flag)
//      {
//#ifdef _MPI
//        BS_ASSERT (false && "MPI: NOT IMPL YET");
//        smart_ptr< /*!mpi_*/cpr_preconditioner<strategy_t> > cpr = ((static_cast< smart_ptr< two_stage_preconditioner<strategy_t> > >(preconditioner))->get_prec_1());
//#else // _MPI
//        smart_ptr< cpr_preconditioner<strategy_t> > cpr = ((static_cast< smart_ptr< two_stage_preconditioner<strategy_t> > >(preconditioner))->get_prec_1());
//#endif // _MPI
//
//        BS_ASSERT (cpr);
//        BS_ASSERT (cpr->get_prop ());
//
//        cpr->get_prop()->set_max_iters(ts_params->get_int(fi_params::AMG_LIN_ITERS_NUM));
//        cpr->get_prop()->set_matbal_tolerance(ts_params->get_float(fi_params::AMG_RESID));
//      }
  }

  int
  jacobian::setup_solver_params (well_model_type model_type, int n_phases, const BS_SP (fi_params) &ts_params)
  {

    if (!ts_params)
      {
        throw bs_exception("Jacobian::setup_solver_params", "ts_params is not inited!");
      }

    if (!solver)
      {
        bs_throw_exception ("Solver is null");
      }
    if (!preconditioner)
      {
        bs_throw_exception ("Preconditioner is null");
      }

    if (solver_is_gmres_flag)
      {
        solver->get_prop ()->set_i (ortonorm_vlen, ts_params->get_int (fi_params::GMRES_ORTONORM_VLEN));
        //static_cast< smart_ptr< gmres_solver2<strategy_t> > >(solver)->m
        //= ts_params->get_int(fi_params::GMRES_ORTONORM_VLEN);
      }

    setup_solver (ts_params);
    setup_preconditioner (ts_params);

    solver->set_prec(preconditioner);
    return 0;
  }

  const BS_SP (lsolver_iface) &
  jacobian::get_solver () const
  {
    return solver;
  }

  const BS_SP (lsolver_iface) &
  jacobian::get_prec () const
  {
    return preconditioner;
  }

  void
  jacobian::init (t_long elements, t_long phases_, t_long secondary_)
  {
    secondary = secondary_;
    phases = phases_;

    matrix = BS_KERNEL.create_object ("mbcsr_matrix");
    flux_conn = BS_KERNEL.create_object ("flux_connections");

    BS_SP (bcsr_matrix_iface) flux = BS_KERNEL.create_object ("bcsr_matrix");
    BS_SP (bcsr_matrix_iface) facility = BS_KERNEL.create_object ("bcsr_matrix");
    BS_SP (bcsr_matrix_iface) accum = BS_KERNEL.create_object ("bcsr_matrix");

    matrix->add_matrix ("flux", flux);
    matrix->add_matrix ("facility", facility);
    matrix->add_matrix ("accum", accum);

    facility->alloc_rows_ptr (elements);

    accum->init (elements, elements, phases, elements);
    t_long *accum_rows = accum->get_rows_ptr ()->data ();
    t_long *accum_cols = accum->get_cols_ind ()->data ();
    t_double *accum_vals = accum->get_values ()->data ();
    // OPENMP
    for (t_long i = 0; i < elements + 1; ++i)
      {
        accum_rows[i] = i;
      }
    for (t_long i = 0; i < elements; ++i)
      {
        accum_cols[i] = i;
      }
    for (t_long i = 0; i < elements * phases * phases; ++i)
      {
        accum_vals[i] = 0;
      }

    rhs = BS_KERNEL.create_object (v_float::bs_type ());
    rhs_flux = BS_KERNEL.create_object (v_float::bs_type ());
    sec_rhs = BS_KERNEL.create_object (v_float::bs_type ());
    ss_diagonal = BS_KERNEL.create_object (v_float::bs_type ());
    sp_diagonal = BS_KERNEL.create_object (v_float::bs_type ());

    cfl_vector = BS_KERNEL.create_object (v_double::bs_type ());
    solution = BS_KERNEL.create_object (v_double::bs_type ());
    sec_solution = BS_KERNEL.create_object (v_double::bs_type ());

    boundary = BS_KERNEL.create_object (v_long::bs_type ());

    rhs->init (elements * phases, 0);
    rhs_flux->init (elements * phases, 0);
    cfl_vector->init (elements * phases, 0);
    solution->init (elements * phases, 0);

    if (secondary > 0)
      {
        sec_rhs->init (secondary * elements, 0);
        ss_diagonal->init (secondary * secondary * elements, 0);
        sp_diagonal->init (secondary * elements * phases, 0);
        sec_solution->init (secondary * elements, 0);
      }
    else
      {
        sec_rhs->init (1, 0);
        ss_diagonal->init (1, 0);
        sp_diagonal->init (1, 0);
        sec_solution->init (1, 0);
      }

    // FIXME: copied from reservoir_simulator
    //index_t N_block_size = cm->n_phases;
    //index_t N_blocks = hdm->get_mesh ()->get_n_active_elements ();
    //// FIXME: wrong init?
    //jmatrix->get_flux_matrix()->get_values ()->init (N_block_size, 0);
    //jmatrix->get_flux_matrix ()->get_values()->init (N_block_size * N_block_size * (2* hdm->get_mesh ()->get_n_connections() + hdm->get_mesh ()->get_n_active_elements()), item_t (0));

    //jmatrix->get_facility_matrix ()->init (N_blocks, N_blocks, N_block_size, 0);
  }

  BS_SP (bcsr_matrix_iface)
  jacobian::get_matrix (std::string const &name) const
  {
    BS_ASSERT (matrix);
    if (name == "trns")
      return flux_conn->get_conn_trans ();

    return matrix->get_matrix (name);
  }

  BS_SP (mbcsr_matrix_iface)
  jacobian::get_matrix () const
  {
    BS_ASSERT (matrix);
    return matrix;
  }

  spv_float
  jacobian::get_ss_diagonal ()
  {
    return ss_diagonal;
  }

  spv_float
  jacobian::get_sp_diagonal ()
  {
    return sp_diagonal;
  }

  spv_float
  jacobian::get_sec_rhs ()
  {
    return sec_rhs;
  }

  spv_float
  jacobian::get_rhs ()
  {
    return rhs;
  }

  spv_float
  jacobian::get_rhs_flux ()
  {
    return rhs_flux;
  }

  spv_float
  jacobian::get_cfl_vector ()
  {
    return cfl_vector;
  }

  spv_double
  jacobian::get_solution ()
  {
    return solution;
  }

  spv_double
  jacobian::get_sec_solution ()
  {
    return sec_solution;
  }

  spv_long
  jacobian::get_boundary ()
  {
    return boundary;
  }

  BS_SP (flux_connections_iface)
  jacobian::get_flux_connections ()
  {
    return flux_conn;
  }

  spv_long
  jacobian::get_m_array ()
  {
    BS_ASSERT (flux_conn);
    return flux_conn->get_matrix_block_idx_minus ();
  }

  spv_long
  jacobian::get_p_array ()
  {
    BS_ASSERT (flux_conn);
    return flux_conn->get_matrix_block_idx_plus ();
  }

  // FIXME:
  void
  jacobian::clear_solution ()
  {
    solution->assign (0);
  }

  // FIXME:
  void
  jacobian::summ_rhs ()
  {
    if (rhs->size () != rhs_flux->size ())
      {
        bs_throw_exception ("rhs and rhs_flux size mismatch");
      }

    t_float *rhs_ = rhs->data ();
    t_float *rhs_flux_ = rhs_flux->data ();

    // OPENMP:
    for (size_t i = 0, cnt = rhs->size (); i < cnt; ++i)
      {
        rhs_[i] += rhs_flux_[i];
      }
  }

  // FIXME:
  void
  jacobian::mult_flux_part (t_double mult)
  {
    spv_double facility = matrix->get_matrix ("facility")->get_values ();
    spv_double flux     = matrix->get_matrix ("flux")->get_values ();
    t_double *facility_ = facility->data ();
    t_double *flux_     = flux->data ();
    t_float *rhs_flux_  = rhs_flux->data ();

    // FIXME: should we multiply facility?
    // OPENMP
    for (size_t i = 0, cnt = facility->size (); i < cnt; ++i)
      {
        facility_[i] *= mult;
      }
    for (size_t i = 0, cnt = flux->size (); i < cnt; ++i)
      {
        flux_[i] *= mult;
      }
    for (size_t i = 0, cnt = rhs_flux->size (); i < cnt; ++i)
      {
        rhs_flux_[i] *= mult;
      }
  }

  // FIXME:
  void
  jacobian::restore_sec_solution ()
  {
    if (secondary > 0)
      {
        if (phases != matrix->get_matrix ("flux")->get_n_block_size ())
          {
            bs_throw_exception ("phases and flux block_size mismatch");
          }

        spv_long rows     = matrix->get_matrix ("flux")->get_rows_ptr ();
        t_float *sp_diag  = sp_diagonal->data ();
        t_double *sol     = solution->data ();
        t_double *sec_sol = sec_solution->data ();
        t_float *sec_rhs_ = sec_rhs->data ();

        // OPENMP
        for (t_long i = 0, cnt = (t_long)rows->size (); i < cnt - 1; ++i)
          {
            t_float *sp_block   = &sp_diag[secondary * phases * i];
            t_double *sol_block = &sol[phases * i];
            sec_sol[i]          = sec_rhs_[i];

            VV_PROD_M (phases, sp_block, sol_block, sec_sol[i]);
          }
      }
  }

  BLUE_SKY_TYPE_STD_CREATE (jacobian);
  BLUE_SKY_TYPE_STD_COPY (jacobian);

  BLUE_SKY_TYPE_IMPL (jacobian, bs_node, "jacobian", "Jacobian", "Jacobian");
};

<|endoftext|>


<commit_before>// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libgen.h>

#include "bin/file.h"

class FileHandle {
 public:
  explicit FileHandle(int fd) : fd_(fd) { }
  ~FileHandle() { }
  int fd() const { return fd_; }
  void set_fd(int fd) { fd_ = fd; }

 private:
  int fd_;

  // DISALLOW_COPY_AND_ASSIGN(FileHandle).
  FileHandle(const FileHandle&);
  void operator=(const FileHandle&);
};

File::~File() {
  // Close the file (unless it's a standard stream).
  if (handle_->fd() > STDERR_FILENO) {
    Close();
  }
  delete handle_;
}

void File::Close() {
  ASSERT(handle_->fd() >= 0);
  int err = close(handle_->fd());
  if (err != 0) {
    const int kBufferSize = 1024;
    char error_message[kBufferSize];
    strerror_r(errno, error_message, kBufferSize);
    fprintf(stderr, "%s\n", error_message);
  }
  handle_->set_fd(kClosedFd);
}

bool File::IsClosed() {
  return handle_->fd() == kClosedFd;
}

int64_t File::Read(void* buffer, int64_t num_bytes) {
  ASSERT(handle_->fd() >= 0);
  return read(handle_->fd(), buffer, num_bytes);
}

int64_t File::Write(const void* buffer, int64_t num_bytes) {
  ASSERT(handle_->fd() >= 0);
  return write(handle_->fd(), buffer, num_bytes);
}

off_t File::Position() {
  ASSERT(handle_->fd() >= 0);
  return lseek(handle_->fd(), 0, SEEK_CUR);
}

void File::Flush() {
  ASSERT(handle_->fd() >= 0);
  fsync(handle_->fd());
}

off_t File::Length() {
  ASSERT(handle_->fd() >= 0);
  off_t position = lseek(handle_->fd(), 0, SEEK_CUR);
  if (position < 0) {
    // The file is not capable of seeking. Return an error.
    return -1;
  }
  off_t result = lseek(handle_->fd(), 0, SEEK_END);
  lseek(handle_->fd(), position, SEEK_SET);
  return result;
}

File* File::OpenFile(const char* name, bool writable) {
  int flags = O_RDONLY;
  if (writable) {
    flags = (O_RDWR | O_CREAT | O_TRUNC);
  }
  int fd = open(name, flags, 0666);
  if (fd < 0) {
    return NULL;
  }
  return new File(name, new FileHandle(fd));
}

bool File::FileExists(const char* name) {
  struct stat st;
  if (stat(name, &st) == 0) {
    return S_ISREG(st.st_mode);  // Deal with symlinks?
  } else {
    return false;
  }
}

bool File::IsAbsolutePath(const char* pathname) {
  return (pathname != NULL && pathname[0] == '/');
}

const char* File::PathSeparator() {
  return "/";
}

const char* File::StringEscapedPathSeparator() {
  return "/";
}
<commit_msg>Fix Mac build.<commit_after>// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libgen.h>

#include "bin/builtin.h"
#include "bin/file.h"

class FileHandle {
 public:
  explicit FileHandle(int fd) : fd_(fd) { }
  ~FileHandle() { }
  int fd() const { return fd_; }
  void set_fd(int fd) { fd_ = fd; }

 private:
  int fd_;

  // DISALLOW_COPY_AND_ASSIGN(FileHandle).
  FileHandle(const FileHandle&);
  void operator=(const FileHandle&);
};

File::~File() {
  // Close the file (unless it's a standard stream).
  if (handle_->fd() > STDERR_FILENO) {
    Close();
  }
  delete handle_;
}

void File::Close() {
  ASSERT(handle_->fd() >= 0);
  int err = close(handle_->fd());
  if (err != 0) {
    const int kBufferSize = 1024;
    char error_message[kBufferSize];
    strerror_r(errno, error_message, kBufferSize);
    fprintf(stderr, "%s\n", error_message);
  }
  handle_->set_fd(kClosedFd);
}

bool File::IsClosed() {
  return handle_->fd() == kClosedFd;
}

int64_t File::Read(void* buffer, int64_t num_bytes) {
  ASSERT(handle_->fd() >= 0);
  return read(handle_->fd(), buffer, num_bytes);
}

int64_t File::Write(const void* buffer, int64_t num_bytes) {
  ASSERT(handle_->fd() >= 0);
  return write(handle_->fd(), buffer, num_bytes);
}

off_t File::Position() {
  ASSERT(handle_->fd() >= 0);
  return lseek(handle_->fd(), 0, SEEK_CUR);
}

void File::Flush() {
  ASSERT(handle_->fd() >= 0);
  fsync(handle_->fd());
}

off_t File::Length() {
  ASSERT(handle_->fd() >= 0);
  off_t position = lseek(handle_->fd(), 0, SEEK_CUR);
  if (position < 0) {
    // The file is not capable of seeking. Return an error.
    return -1;
  }
  off_t result = lseek(handle_->fd(), 0, SEEK_END);
  lseek(handle_->fd(), position, SEEK_SET);
  return result;
}

File* File::OpenFile(const char* name, bool writable) {
  int flags = O_RDONLY;
  if (writable) {
    flags = (O_RDWR | O_CREAT | O_TRUNC);
  }
  int fd = open(name, flags, 0666);
  if (fd < 0) {
    return NULL;
  }
  return new File(name, new FileHandle(fd));
}

bool File::FileExists(const char* name) {
  struct stat st;
  if (stat(name, &st) == 0) {
    return S_ISREG(st.st_mode);  // Deal with symlinks?
  } else {
    return false;
  }
}

bool File::IsAbsolutePath(const char* pathname) {
  return (pathname != NULL && pathname[0] == '/');
}

const char* File::PathSeparator() {
  return "/";
}

const char* File::StringEscapedPathSeparator() {
  return "/";
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "exception.h"

#ifdef Q_OS_LINUX
#include <execinfo.h>
#include <cxxabi.h>
#endif

#include <coreplugin/icore.h>

#include <QCoreApplication>
#include <QMessageBox>

static void showAsyncWarning(const QString &title, const QString &desciption)
{
    QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning, title, desciption, QMessageBox::Ok, Core::ICore::dialogParent());
    messageBox->setAttribute(Qt::WA_DeleteOnClose);
    messageBox->setModal(true);
    messageBox->show();
}

/*!
\defgroup CoreExceptions
*/
/*!
\class QmlDesigner::Exception
\ingroup CoreExceptions
\brief The Exception class is the abstract base class for all exceptions.

    Exceptions should be used if there is no other way to indicate that
    something is going wrong. For example,
    the result would be a inconsistent model or a crash.
*/

namespace QmlDesigner {

#ifdef Q_OS_LINUX
const char* demangle(const char* name)
{
   char buf[1024];
   size_t size = 1024;
   int status;
   char* res;
   res = abi::__cxa_demangle(name,
     buf,
     &size,
     &status);
   return res;
}
#else
const char* demangle(const char* name)
{
   return name;
}
#endif

bool Exception::s_shouldAssert = false;

void Exception::setShouldAssert(bool assert)
{
    s_shouldAssert = assert;
}

bool Exception::shouldAssert()
{
    return s_shouldAssert;
}

bool Exception::warnAboutException()
{
    static bool warnException = !qgetenv("QTCREATOR_QTQUICKDESIGNER_WARN_EXCEPTION").isEmpty();
    return warnException;
}

/*!
    Constructs an exception. \a line uses the __LINE__ macro, \a function uses
    the __FUNCTION__ or the Q_FUNC_INFO macro, and \a file uses
    the __FILE__ macro.
*/
Exception::Exception(int line,
              const QString &function,
              const QString &file)
  : m_line(line),
    m_function(function),
    m_file(file)
{
#ifdef Q_OS_LINUX
    void * array[50];
    int nSize = backtrace(array, 50);
    char ** symbols = backtrace_symbols(array, nSize);

    for (int i = 0; i < nSize; i++)
    {
        m_backTrace.append(QString("%1\n").arg(symbols[i]));
    }

    free(symbols);
#endif

if (s_shouldAssert)
    Q_ASSERT_X(false, function.toUtf8(), QString("%1:%2 - %3").arg(file).arg(line).arg(function).toUtf8());
}

Exception::~Exception()
{
}

/*!
    Returns the unmangled backtrace of this exception as a string.
*/
QString Exception::backTrace() const
{
    return m_backTrace;
}

void Exception::createWarning() const
{
    if (warnAboutException())
        qDebug() << *this;
}

/*!
    Returns the optional description of this exception as a string.
*/
QString Exception::description() const
{
    return QString("file: %1, function: %2, line: %3").arg(m_file, m_function, QString::number(m_line));
}

/*!
    Shows message in a message box.
*/
void Exception::showException(const QString &title) const
{
    QString t = title.isEmpty() ? QCoreApplication::translate("QmlDesigner", "Error") : title;
    showAsyncWarning(t, description());
}

/*!
    Returns the line number where this exception was thrown as an integer.
*/
int Exception::line() const
{
    return m_line;
}

/*!
    Returns the function name where this exception was thrown as a string.
*/
QString Exception::function() const
{
    return m_function;
}

/*!
    Returns the file name where this exception was thrown as a string.
*/
QString Exception::file() const
{
    return m_file;
}

QDebug operator<<(QDebug debug, const Exception &exception)
{
    debug.nospace() << "Exception: " << exception.type() << "\n"
                       "Function:  " << exception.function() << "\n"
                       "File:      " << exception.file() << "\n"
                       "Line:      " << exception.line() << "\n";
    if (!exception.description().isEmpty())
        debug.nospace() << exception.description();

    if (!exception.backTrace().isEmpty())
        debug.nospace() << exception.backTrace();

    return debug.space();
}

/*!
\fn QString Exception::type() const
Returns the type of this exception as a string.
*/
}
<commit_msg>QmlDesigner: Fix short name<commit_after>/****************************************************************************
**
** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "exception.h"

#ifdef Q_OS_LINUX
#include <execinfo.h>
#include <cxxabi.h>
#endif

#include <coreplugin/icore.h>

#include <QCoreApplication>
#include <QMessageBox>

static void showAsyncWarning(const QString &title, const QString &desciption)
{
    QMessageBox *messageBox = new QMessageBox(QMessageBox::Warning, title, desciption, QMessageBox::Ok, Core::ICore::dialogParent());
    messageBox->setAttribute(Qt::WA_DeleteOnClose);
    messageBox->setModal(true);
    messageBox->show();
}

/*!
\defgroup CoreExceptions
*/
/*!
\class QmlDesigner::Exception
\ingroup CoreExceptions
\brief The Exception class is the abstract base class for all exceptions.

    Exceptions should be used if there is no other way to indicate that
    something is going wrong. For example,
    the result would be a inconsistent model or a crash.
*/

namespace QmlDesigner {

#ifdef Q_OS_LINUX
const char* demangle(const char* name)
{
   char buf[1024];
   size_t size = 1024;
   int status;
   char* res;
   res = abi::__cxa_demangle(name,
     buf,
     &size,
     &status);
   return res;
}
#else
const char* demangle(const char* name)
{
   return name;
}
#endif

bool Exception::s_shouldAssert = false;

void Exception::setShouldAssert(bool assert)
{
    s_shouldAssert = assert;
}

bool Exception::shouldAssert()
{
    return s_shouldAssert;
}

bool Exception::warnAboutException()
{
    static bool warnException = !qgetenv("QTCREATOR_QTQUICKDESIGNER_WARN_EXCEPTION").isEmpty();
    return warnException;
}

/*!
    Constructs an exception. \a line uses the __LINE__ macro, \a function uses
    the __FUNCTION__ or the Q_FUNC_INFO macro, and \a file uses
    the __FILE__ macro.
*/
Exception::Exception(int line,
              const QString &function,
              const QString &file)
  : m_line(line),
    m_function(function),
    m_file(file)
{
#ifdef Q_OS_LINUX
    void * array[50];
    int nSize = backtrace(array, 50);
    char ** symbols = backtrace_symbols(array, nSize);

    for (int i = 0; i < nSize; i++)
    {
        m_backTrace.append(QString("%1\n").arg(symbols[i]));
    }

    free(symbols);
#endif

if (s_shouldAssert)
    Q_ASSERT_X(false, function.toUtf8(), QString("%1:%2 - %3").arg(file).arg(line).arg(function).toUtf8());
}

Exception::~Exception()
{
}

/*!
    Returns the unmangled backtrace of this exception as a string.
*/
QString Exception::backTrace() const
{
    return m_backTrace;
}

void Exception::createWarning() const
{
    if (warnAboutException())
        qDebug() << *this;
}

/*!
    Returns the optional description of this exception as a string.
*/
QString Exception::description() const
{
    return QString("file: %1, function: %2, line: %3").arg(m_file, m_function, QString::number(m_line));
}

/*!
    Shows message in a message box.
*/
void Exception::showException(const QString &title) const
{
    QString composedTitle = title.isEmpty() ? QCoreApplication::translate("QmlDesigner", "Error") : title;
    showAsyncWarning(composedTitle, description());
}

/*!
    Returns the line number where this exception was thrown as an integer.
*/
int Exception::line() const
{
    return m_line;
}

/*!
    Returns the function name where this exception was thrown as a string.
*/
QString Exception::function() const
{
    return m_function;
}

/*!
    Returns the file name where this exception was thrown as a string.
*/
QString Exception::file() const
{
    return m_file;
}

QDebug operator<<(QDebug debug, const Exception &exception)
{
    debug.nospace() << "Exception: " << exception.type() << "\n"
                       "Function:  " << exception.function() << "\n"
                       "File:      " << exception.file() << "\n"
                       "Line:      " << exception.line() << "\n";
    if (!exception.description().isEmpty())
        debug.nospace() << exception.description();

    if (!exception.backTrace().isEmpty())
        debug.nospace() << exception.backTrace();

    return debug.space();
}

/*!
\fn QString Exception::type() const
Returns the type of this exception as a string.
*/
}
<|endoftext|>


<commit_before>// Copyright (c) 2014-2017 Michael J. Sullivan
// Use of this source code is governed by an MIT-style license that can be
// found in the LICENSE file.

#include <rmc++.h>
#include <utility>
#include <functional>
#include <memory>
#include "epoch_rmc.hpp"

// Very very closely modeled after crossbeam by aturon.

namespace rmclib {
/////////////////////////////

const int kNumEpochs = 3;

thread_local LocalEpoch Epoch::local_epoch_;
rmc::atomic<Participant::Ptr> Participant::participants_;
static ConcurrentBag global_garbage_[kNumEpochs];

/// BEGIN SNIP
static rmc::atomic<uintptr_t> global_epoch_{0};

/////// Participant is where most of the interesting stuff happens
bool Participant::quickEnter() noexcept {
    PEDGE(enter, body);

    uintptr_t new_count = in_critical_ + 1;
    // XXX: THIS IS ACTUALLY FUCKED BECAUSE WE DO NOT HAVE FUCKING
    // RELEASE SEQUENCES
    L(enter, in_critical_ = new_count);
    // Nothing to do if we were already in a critical section
    if (new_count > 1) return false;

    // Copy the global epoch to the local one;
    uintptr_t global_epoch = L(enter, global_epoch_);
    epoch_ = global_epoch;
    LPOST(body);
    return true;
}

void Participant::enter() noexcept {
    uintptr_t epoch = epoch_;
    if (!quickEnter()) return;

    // If the epoch has changed, garbage collect
    if (epoch != epoch_) {
        garbage_.collect();
    }

    if (garbage_.needsCollect()) {
        tryCollect();
    }
}

void Participant::exit() noexcept {
    VEDGE(pre, exit);
    uintptr_t new_count = in_critical_ - 1;
    L(exit, in_critical_ = new_count);
}

bool Participant::tryCollect() {
    XEDGE(load_head, a);
    // This could maybe be XEDGE but making it VEDGE lets us make the
    // invariant -vt-> based.
    VEDGE(a, update_epoch);
    VEDGE(update_epoch, collect); // XXX: discount double check
    XEDGE(collect, update_local);

    uintptr_t cur_epoch = epoch_;

    // Check whether all active threads are in the current epoch so we
    // can advance it.
    // As we do it, we lazily clean up exited threads.
try_again:
    rmc::atomic<Participant::Ptr> *prevp = &participants_;
    Participant::Ptr cur = L(load_head, *prevp);
    while (cur) {
        Participant::Ptr next = L(a, cur->next_);
        if (next.tag()) {
            // This node has exited. Try to unlink it from the
            // list. This will fail if it's already been unlinked or
            // the previous node has exited; in those cases, we start
            // back over at the head of the list.
            next = Ptr(next, 0); // clear next's tag
            if (L(a, prevp->compare_exchange_strong(cur, next))) {
                Guard g(this);
                g.unlinked(cur.ptr());
            } else {
                goto try_again;
            }
        } else {
            // We can only advance the epoch if every thread in a critical
            // section is in the current epoch.
            if (L(a, cur->in_critical_) && L(a, cur->epoch_) != cur_epoch) {
                return false;
            }
            prevp = &cur->next_;
        }

        cur = next;
    }

    // Try to advance the global epoch
    uintptr_t new_epoch = cur_epoch + 1;
    if (!L(update_epoch,
           global_epoch_.compare_exchange_strong(cur_epoch, new_epoch))) {
        return false;
    }

    // Garbage collect
    LS(collect, {
        global_garbage_[(new_epoch+1) % kNumEpochs].collect();
        garbage_.collect();
    });
    // Now that the collection is done, we can safely update our
    // local epoch.
    // XXX: can we???
    L(update_local, epoch_ = new_epoch);

    return true;
}

// Participant lifetime management
Participant *Participant::enroll() {
    VEDGE(init_p, cas);

    Participant *p = L(init_p, new Participant());

    Participant::Ptr head = participants_;
    for (;;) {
        L(init_p, p->next_ = head);
        if (L(cas, participants_.compare_exchange_weak(head, p))) break;
    }

    return p;
}
void Participant::shutdown() noexcept {
    VEDGE(before, exit);
    LPRE(before);

    Participant::Ptr next = next_;
    Participant::Ptr exited_next;
    do {
        exited_next = Participant::Ptr(next, 1);
    } while (!L(exit, next_.compare_exchange_weak(next, exited_next)));

}
/// END SNIP

/////////////
void RealLocalGarbage::collectBag(Bag &bag) {
    for (auto f : bag) {
        f();
    }
    // XXX: should we shrink capacity?
    bag.clear();
}

void RealLocalGarbage::collect() {
    if (size() == 0) return;

    collectBag(old_);
    std::swap(old_, cur_);
    std::swap(cur_, new_);
}

void RealLocalGarbage::migrateGarbage() {
    // We put all three local bags into the current global bag.
    // We could do better than this but why bother, I think.
    auto cleanup = [old = std::move(old_),
                    cur = std::move(cur_),
                    newp = std::move(new_)]() mutable {
        collectBag(old);
        collectBag(cur);
        collectBag(newp);
    };
    global_garbage_[global_epoch_ % kNumEpochs].registerCleanup(cleanup);
}

void DummyLocalGarbage::registerCleanup(GarbageCleanup f) {
    global_garbage_[global_epoch_ % kNumEpochs].registerCleanup(f);
}

/////////////
void ConcurrentBag::registerCleanup(ConcurrentBag::Cleanup f) {
    stack_.pushNode(new Node(std::move(f)));
}

void ConcurrentBag::collect() {
    // Pop the whole stack off
    // Since we only ever unconditionally destroy the whole stack,
    // we don't need to worry about ABA really.
    // (Which for stacks comes up if pop() believes that the address
    // of a node being the same means the next pointer is also...)
    std::unique_ptr<ConcurrentBag::Node> head(stack_.popAll());

    while (head) {
        head->data_();
        head.reset(head->next_);
    }
}

}
<commit_msg>ugh release sequences<commit_after>// Copyright (c) 2014-2017 Michael J. Sullivan
// Use of this source code is governed by an MIT-style license that can be
// found in the LICENSE file.

#include <rmc++.h>
#include <utility>
#include <functional>
#include <memory>
#include "epoch_rmc.hpp"

// Very very closely modeled after crossbeam by aturon.

namespace rmclib {
/////////////////////////////

const int kNumEpochs = 3;

thread_local LocalEpoch Epoch::local_epoch_;
rmc::atomic<Participant::Ptr> Participant::participants_;
static ConcurrentBag global_garbage_[kNumEpochs];

/// BEGIN SNIP
static rmc::atomic<uintptr_t> global_epoch_{0};

/////// Participant is where most of the interesting stuff happens
bool Participant::quickEnter() noexcept {
    PEDGE(enter, body);

    uintptr_t new_count = in_critical_ + 1;
    L(enter, in_critical_ = new_count);
    // Nothing to do if we were already in a critical section
    if (new_count > 1) return false;

    // Copy the global epoch to the local one;
    uintptr_t global_epoch = L(enter, global_epoch_);
    epoch_ = global_epoch;
    LPOST(body);
    return true;
}

void Participant::enter() noexcept {
    uintptr_t epoch = epoch_;
    if (!quickEnter()) return;

    // If the epoch has changed, garbage collect
    if (epoch != epoch_) {
        garbage_.collect();
    }

    if (garbage_.needsCollect()) {
        tryCollect();
    }
}

void Participant::exit() noexcept {
    // This is actually super unfortunate. quickEnter() will
    // subsequently write to in_critical_, and we need the body of a
    // critical section to be visible to code that reads from that
    // subsequent write as well as this one.
    // In C++11, we would make the write to in_critical_ be a release
    // and the convoluted release sequence rules would save us.
    VEDGE(pre, exit);
    LPOST(exit);
    uintptr_t new_count = in_critical_ - 1;
    L(__exit, in_critical_ = new_count);
}

bool Participant::tryCollect() {
    XEDGE(load_head, a);
    VEDGE(a, update_epoch);
    VEDGE(update_epoch, collect); // XXX: discount double check
    XEDGE(collect, update_local);

    uintptr_t cur_epoch = epoch_;

    // Check whether all active threads are in the current epoch so we
    // can advance it.
    // As we do it, we lazily clean up exited threads.
try_again:
    rmc::atomic<Participant::Ptr> *prevp = &participants_;
    Participant::Ptr cur = L(load_head, *prevp);
    while (cur) {
        Participant::Ptr next = L(a, cur->next_);
        if (next.tag()) {
            // This node has exited. Try to unlink it from the
            // list. This will fail if it's already been unlinked or
            // the previous node has exited; in those cases, we start
            // back over at the head of the list.
            next = Ptr(next, 0); // clear next's tag
            if (L(a, prevp->compare_exchange_strong(cur, next))) {
                Guard g(this);
                g.unlinked(cur.ptr());
            } else {
                goto try_again;
            }
        } else {
            // We can only advance the epoch if every thread in a critical
            // section is in the current epoch.
            if (L(a, cur->in_critical_) && L(a, cur->epoch_) != cur_epoch) {
                return false;
            }
            prevp = &cur->next_;
        }

        cur = next;
    }

    // Try to advance the global epoch
    uintptr_t new_epoch = cur_epoch + 1;
    if (!L(update_epoch,
           global_epoch_.compare_exchange_strong(cur_epoch, new_epoch))) {
        return false;
    }

    // Garbage collect
    LS(collect, {
        global_garbage_[(new_epoch+1) % kNumEpochs].collect();
        garbage_.collect();
    });
    // Now that the collection is done, we can safely update our
    // local epoch.
    // XXX: can we???
    L(update_local, epoch_ = new_epoch);

    return true;
}

// Participant lifetime management
Participant *Participant::enroll() {
    VEDGE(init_p, cas);

    Participant *p = L(init_p, new Participant());

    Participant::Ptr head = participants_;
    for (;;) {
        L(init_p, p->next_ = head);
        if (L(cas, participants_.compare_exchange_weak(head, p))) break;
    }

    return p;
}
void Participant::shutdown() noexcept {
    VEDGE(before, exit);
    LPRE(before);

    Participant::Ptr next = next_;
    Participant::Ptr exited_next;
    do {
        exited_next = Participant::Ptr(next, 1);
    } while (!L(exit, next_.compare_exchange_weak(next, exited_next)));

}
/// END SNIP

/////////////
void RealLocalGarbage::collectBag(Bag &bag) {
    for (auto f : bag) {
        f();
    }
    // XXX: should we shrink capacity?
    bag.clear();
}

void RealLocalGarbage::collect() {
    if (size() == 0) return;

    collectBag(old_);
    std::swap(old_, cur_);
    std::swap(cur_, new_);
}

void RealLocalGarbage::migrateGarbage() {
    // We put all three local bags into the current global bag.
    // We could do better than this but why bother, I think.
    auto cleanup = [old = std::move(old_),
                    cur = std::move(cur_),
                    newp = std::move(new_)]() mutable {
        collectBag(old);
        collectBag(cur);
        collectBag(newp);
    };
    global_garbage_[global_epoch_ % kNumEpochs].registerCleanup(cleanup);
}

void DummyLocalGarbage::registerCleanup(GarbageCleanup f) {
    global_garbage_[global_epoch_ % kNumEpochs].registerCleanup(f);
}

/////////////
void ConcurrentBag::registerCleanup(ConcurrentBag::Cleanup f) {
    stack_.pushNode(new Node(std::move(f)));
}

void ConcurrentBag::collect() {
    // Pop the whole stack off
    // Since we only ever unconditionally destroy the whole stack,
    // we don't need to worry about ABA really.
    // (Which for stacks comes up if pop() believes that the address
    // of a node being the same means the next pointer is also...)
    std::unique_ptr<ConcurrentBag::Node> head(stack_.popAll());

    while (head) {
        head->data_();
        head.reset(head->next_);
    }
}

}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "qmlprojectapplicationwizard.h"

#include "qmlprojectconstants.h"

#include <app/app_version.h>
#include <projectexplorer/customwizard/customwizard.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <qtsupport/qtsupportconstants.h>

#include <QIcon>

#include <QPainter>
#include <QPixmap>

#include <QDir>
#include <QTextStream>
#include <QCoreApplication>

namespace QmlProjectManager {
namespace Internal {

QmlProjectApplicationWizardDialog::QmlProjectApplicationWizardDialog(QWidget *parent,
                                                                     const Core::WizardDialogParameters &parameters) :
    ProjectExplorer::BaseProjectWizardDialog(parent, parameters)
{
    setWindowTitle(tr("New Qt Quick UI Project"));
    setIntroDescription(tr("This wizard generates a Qt Quick UI project."));
}

QmlProjectApplicationWizard::QmlProjectApplicationWizard()
    : Core::BaseFileWizard(parameters())
{ }

QmlProjectApplicationWizard::~QmlProjectApplicationWizard()
{ }

Core::FeatureSet QmlProjectApplicationWizard::requiredFeatures() const
{
    return Core::Feature(QtSupport::Constants::FEATURE_QT_QUICK) | Core::Feature(QtSupport::Constants::FEATURE_QMLPROJECT);
}

Core::BaseFileWizardParameters QmlProjectApplicationWizard::parameters()
{
    Core::BaseFileWizardParameters parameters(ProjectWizard);
    parameters.setIcon(QIcon(QLatin1String(QtSupport::Constants::QML_WIZARD_ICON)));
    parameters.setDisplayName(tr("Qt Quick UI"));
    parameters.setId(QLatin1String("QB.QML Application"));

    parameters.setDescription(tr("Creates a Qt Quick UI project with a single "
        "QML file that contains the main view.\n\n"
        "You can review Qt Quick UI projects in the QML Viewer and you need not build them. "
        "You do not need to have the development environment installed "
        "on your computer to create and run this type of projects.\n\nRequires Qt 5.0 or newer."));
    parameters.setCategory(QLatin1String(ProjectExplorer::Constants::QT_APPLICATION_WIZARD_CATEGORY));
    parameters.setDisplayCategory(QT_TRANSLATE_NOOP("ProjectExplorer", "Qt Application"));
    return parameters;
}

QWizard *QmlProjectApplicationWizard::createWizardDialog(QWidget *parent,
                                                         const Core::WizardDialogParameters &wizardDialogParameters) const
{
    QmlProjectApplicationWizardDialog *wizard = new QmlProjectApplicationWizardDialog(parent, wizardDialogParameters);

    wizard->setProjectName(QmlProjectApplicationWizardDialog::uniqueProjectName(wizardDialogParameters.defaultPath()));

    wizard->addExtensionPages(wizardDialogParameters.extensionPages());

    return wizard;
}

Core::GeneratedFiles QmlProjectApplicationWizard::generateFiles(const QWizard *w,
                                                     QString *errorMessage) const
{
    Q_UNUSED(errorMessage)

    const QmlProjectApplicationWizardDialog *wizard = qobject_cast<const QmlProjectApplicationWizardDialog *>(w);
    const QString projectName = wizard->projectName();
    const QString projectPath = wizard->path() + QLatin1Char('/') + projectName;

    const QString creatorFileName = Core::BaseFileWizard::buildFileName(projectPath,
                                                                        projectName,
                                                                        QLatin1String("qmlproject"));

    const QString mainFileName = Core::BaseFileWizard::buildFileName(projectPath,
                                                                     projectName,
                                                                     QLatin1String("qml"));

    QString contents;
    {
        QTextStream out(&contents);

        out
            << "import QtQuick 2.0" << endl
            << endl
            << "Rectangle {" << endl
            << "    width: 360" << endl
            << "    height: 360" << endl
            << "    Text {" << endl
            << "        anchors.centerIn: parent" << endl
            << "        text: \"Hello World\"" << endl
            << "    }" << endl
            << "    MouseArea {" << endl
            << "        anchors.fill: parent" << endl
            << "        onClicked: {" << endl
            << "            Qt.quit();" << endl
            << "        }" << endl
            << "    }" << endl
            << "}" << endl;
    }
    Core::GeneratedFile generatedMainFile(mainFileName);
    generatedMainFile.setContents(contents);
    generatedMainFile.setAttributes(Core::GeneratedFile::OpenEditorAttribute);

    QString projectContents;
    {
        QTextStream out(&projectContents);

        out << "/* File generated by Qt Creator, version " << Core::Constants::IDE_VERSION_LONG << " */" << endl
            << endl
            << "import QmlProject 1.1" << endl
            << endl
            << "Project {" << endl
            << "    mainFile: \"" << QDir(projectPath).relativeFilePath(mainFileName) << '"' << endl
            << endl
            << "    /* Include .qml, .js, and image files from current directory and subdirectories */" << endl
            << "    QmlFiles {" << endl
            << "        directory: \".\"" << endl
            << "    }" << endl
            << "    JavaScriptFiles {" << endl
            << "        directory: \".\"" << endl
            << "    }" << endl
            << "    ImageFiles {" << endl
            << "        directory: \".\"" << endl
            << "    }" << endl
            << "    /* List of plugin directories passed to QML runtime */" << endl
            << "    // importPaths: [ \"../exampleplugin\" ]" << endl
            << "}" << endl;
    }
    Core::GeneratedFile generatedCreatorFile(creatorFileName);
    generatedCreatorFile.setContents(projectContents);
    generatedCreatorFile.setAttributes(Core::GeneratedFile::OpenProjectAttribute);

    Core::GeneratedFiles files;
    files.append(generatedMainFile);
    files.append(generatedCreatorFile);

    return files;
}

bool QmlProjectApplicationWizard::postGenerateFiles(const QWizard *, const Core::GeneratedFiles &l, QString *errorMessage)
{
    return ProjectExplorer::CustomProjectWizard::postGenerateOpen(l, errorMessage);

}

} // namespace Internal
} // namespace QmlProjectManager

<commit_msg>QtQuickUI: Adapt wizard to only show up if Qt 5 is registered<commit_after>/****************************************************************************
**
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "qmlprojectapplicationwizard.h"

#include "qmlprojectconstants.h"

#include <app/app_version.h>
#include <projectexplorer/customwizard/customwizard.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <qtsupport/qtsupportconstants.h>

#include <QIcon>

#include <QPainter>
#include <QPixmap>

#include <QDir>
#include <QTextStream>
#include <QCoreApplication>

namespace QmlProjectManager {
namespace Internal {

QmlProjectApplicationWizardDialog::QmlProjectApplicationWizardDialog(QWidget *parent,
                                                                     const Core::WizardDialogParameters &parameters) :
    ProjectExplorer::BaseProjectWizardDialog(parent, parameters)
{
    setWindowTitle(tr("New Qt Quick UI Project"));
    setIntroDescription(tr("This wizard generates a Qt Quick UI project."));
}

QmlProjectApplicationWizard::QmlProjectApplicationWizard()
    : Core::BaseFileWizard(parameters())
{ }

QmlProjectApplicationWizard::~QmlProjectApplicationWizard()
{ }

Core::FeatureSet QmlProjectApplicationWizard::requiredFeatures() const
{
    return Core::Feature(QtSupport::Constants::FEATURE_QT_QUICK_2) | Core::Feature(QtSupport::Constants::FEATURE_QMLPROJECT);
}

Core::BaseFileWizardParameters QmlProjectApplicationWizard::parameters()
{
    Core::BaseFileWizardParameters parameters(ProjectWizard);
    parameters.setIcon(QIcon(QLatin1String(QtSupport::Constants::QML_WIZARD_ICON)));
    parameters.setDisplayName(tr("Qt Quick UI"));
    parameters.setId(QLatin1String("QB.QML Application"));

    parameters.setDescription(tr("Creates a Qt Quick UI project with a single "
        "QML file that contains the main view.\n\n"
        "You can review Qt Quick UI projects in the QML Viewer and you need not build them. "
        "You do not need to have the development environment installed "
        "on your computer to create and run this type of projects.\n\nRequires Qt 5.0 or newer."));
    parameters.setCategory(QLatin1String(ProjectExplorer::Constants::QT_APPLICATION_WIZARD_CATEGORY));
    parameters.setDisplayCategory(QT_TRANSLATE_NOOP("ProjectExplorer", "Qt Application"));
    return parameters;
}

QWizard *QmlProjectApplicationWizard::createWizardDialog(QWidget *parent,
                                                         const Core::WizardDialogParameters &wizardDialogParameters) const
{
    QmlProjectApplicationWizardDialog *wizard = new QmlProjectApplicationWizardDialog(parent, wizardDialogParameters);

    wizard->setProjectName(QmlProjectApplicationWizardDialog::uniqueProjectName(wizardDialogParameters.defaultPath()));

    wizard->addExtensionPages(wizardDialogParameters.extensionPages());

    return wizard;
}

Core::GeneratedFiles QmlProjectApplicationWizard::generateFiles(const QWizard *w,
                                                     QString *errorMessage) const
{
    Q_UNUSED(errorMessage)

    const QmlProjectApplicationWizardDialog *wizard = qobject_cast<const QmlProjectApplicationWizardDialog *>(w);
    const QString projectName = wizard->projectName();
    const QString projectPath = wizard->path() + QLatin1Char('/') + projectName;

    const QString creatorFileName = Core::BaseFileWizard::buildFileName(projectPath,
                                                                        projectName,
                                                                        QLatin1String("qmlproject"));

    const QString mainFileName = Core::BaseFileWizard::buildFileName(projectPath,
                                                                     projectName,
                                                                     QLatin1String("qml"));

    QString contents;
    {
        QTextStream out(&contents);

        out
            << "import QtQuick 2.0" << endl
            << endl
            << "Rectangle {" << endl
            << "    width: 360" << endl
            << "    height: 360" << endl
            << "    Text {" << endl
            << "        anchors.centerIn: parent" << endl
            << "        text: \"Hello World\"" << endl
            << "    }" << endl
            << "    MouseArea {" << endl
            << "        anchors.fill: parent" << endl
            << "        onClicked: {" << endl
            << "            Qt.quit();" << endl
            << "        }" << endl
            << "    }" << endl
            << "}" << endl;
    }
    Core::GeneratedFile generatedMainFile(mainFileName);
    generatedMainFile.setContents(contents);
    generatedMainFile.setAttributes(Core::GeneratedFile::OpenEditorAttribute);

    QString projectContents;
    {
        QTextStream out(&projectContents);

        out << "/* File generated by Qt Creator, version " << Core::Constants::IDE_VERSION_LONG << " */" << endl
            << endl
            << "import QmlProject 1.1" << endl
            << endl
            << "Project {" << endl
            << "    mainFile: \"" << QDir(projectPath).relativeFilePath(mainFileName) << '"' << endl
            << endl
            << "    /* Include .qml, .js, and image files from current directory and subdirectories */" << endl
            << "    QmlFiles {" << endl
            << "        directory: \".\"" << endl
            << "    }" << endl
            << "    JavaScriptFiles {" << endl
            << "        directory: \".\"" << endl
            << "    }" << endl
            << "    ImageFiles {" << endl
            << "        directory: \".\"" << endl
            << "    }" << endl
            << "    /* List of plugin directories passed to QML runtime */" << endl
            << "    // importPaths: [ \"../exampleplugin\" ]" << endl
            << "}" << endl;
    }
    Core::GeneratedFile generatedCreatorFile(creatorFileName);
    generatedCreatorFile.setContents(projectContents);
    generatedCreatorFile.setAttributes(Core::GeneratedFile::OpenProjectAttribute);

    Core::GeneratedFiles files;
    files.append(generatedMainFile);
    files.append(generatedCreatorFile);

    return files;
}

bool QmlProjectApplicationWizard::postGenerateFiles(const QWizard *, const Core::GeneratedFiles &l, QString *errorMessage)
{
    return ProjectExplorer::CustomProjectWizard::postGenerateOpen(l, errorMessage);

}

} // namespace Internal
} // namespace QmlProjectManager

<|endoftext|>


<commit_before><commit_msg>Move flag file extensions/bundled/buildid -> extensions/buildid<commit_after><|endoftext|>