<commit_before>/*
Copyright (c) 2015 - present Advanced Micro Devices, Inc. All rights reserved.

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

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

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

#include <hip/hip_runtime.h>
#include "hip_internal.hpp"

thread_local std::unordered_set<amd::HostQueue*> streamSet;

static hipError_t ihipStreamCreateWithFlags(hipStream_t *stream, unsigned int flags) {
  amd::Device* device = hip::getCurrentContext()->devices()[0];

  amd::HostQueue* queue = new amd::HostQueue(*hip::getCurrentContext(), *device, 0,
                                             amd::CommandQueue::RealTimeDisabled,
                                             amd::CommandQueue::Priority::Normal);

  if (!(flags & hipStreamNonBlocking)) {
    hip::syncStreams();
    streamSet.insert(queue);
  }

  if (queue == nullptr) {
    return hipErrorOutOfMemory;
  }

  *stream = reinterpret_cast<hipStream_t>(as_cl(queue));

  return hipSuccess;
}

hipError_t hipStreamCreateWithFlags(hipStream_t *stream, unsigned int flags) {
  HIP_INIT_API(stream, flags);

  return ihipStreamCreateWithFlags(stream, flags);
}

hipError_t hipStreamCreate(hipStream_t *stream) {
  HIP_INIT_API(stream);

  return ihipStreamCreateWithFlags(stream, hipStreamDefault);
}

hipError_t hipStreamGetFlags(hipStream_t stream, unsigned int *flags) {
  HIP_INIT_API(stream, flags);

  amd::HostQueue* hostQueue = as_amd(reinterpret_cast<cl_command_queue>(stream))->asHostQueue();
  auto it = streamSet.find(hostQueue);

  if(flags != nullptr) {
    *flags = (it != streamSet.end()) ? hipStreamNonBlocking : hipStreamDefault;
  } else {
    return hipErrorInvalidValue;
  }

  return hipSuccess;
}

hipError_t hipStreamSynchronize(hipStream_t stream) {
  HIP_INIT_API(stream);

  amd::HostQueue* hostQueue;

  if (stream == nullptr) {
    hostQueue = hip::getNullStream();
  } else {
    hostQueue = as_amd(reinterpret_cast<cl_command_queue>(stream))->asHostQueue();
  }

  if (hostQueue == nullptr) {
    return hipErrorUnknown;
  }

  hostQueue->finish();

  return hipSuccess;
}

hipError_t hipStreamDestroy(hipStream_t stream) {
  HIP_INIT_API(stream);

  if (stream == nullptr) {
    return hipErrorInvalidResourceHandle;
  }

  amd::HostQueue* hostQueue = as_amd(reinterpret_cast<cl_command_queue>(stream))->asHostQueue();

  streamSet.erase(hostQueue);

  hostQueue->release();

  return hipSuccess;
}

hipError_t hipStreamWaitEvent(hipStream_t stream, hipEvent_t event, unsigned int flags) {
  HIP_INIT_API(stream, event, flags);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipStreamQuery(hipStream_t stream) {
  HIP_INIT_API(stream);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipStreamAddCallback(hipStream_t stream, hipStreamCallback_t callback, void* userData,
                                unsigned int flags) {
  HIP_INIT_API(stream, callback, userData, flags);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

<commit_msg>P4 to Git Change 1552807 by skudchad@skudchad_test2_win_opencl on 2018/05/09 18:08:07<commit_after>/*
Copyright (c) 2015 - present Advanced Micro Devices, Inc. All rights reserved.

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

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

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

#include <hip/hip_runtime.h>
#include "hip_internal.hpp"

thread_local std::unordered_set<amd::HostQueue*> streamSet;

static hipError_t ihipStreamCreateWithFlags(hipStream_t *stream, unsigned int flags) {
  amd::Device* device = hip::getCurrentContext()->devices()[0];

  amd::HostQueue* queue = new amd::HostQueue(*hip::getCurrentContext(), *device, 0,
                                             amd::CommandQueue::RealTimeDisabled,
                                             amd::CommandQueue::Priority::Normal);

  if (queue == nullptr || !queue->create()) {
    return hipErrorOutOfMemory;
  }

  if (!(flags & hipStreamNonBlocking)) {
    hip::syncStreams();
    streamSet.insert(queue);
  }

  *stream = reinterpret_cast<hipStream_t>(as_cl(queue));

  return hipSuccess;
}

hipError_t hipStreamCreateWithFlags(hipStream_t *stream, unsigned int flags) {
  HIP_INIT_API(stream, flags);

  return ihipStreamCreateWithFlags(stream, flags);
}

hipError_t hipStreamCreate(hipStream_t *stream) {
  HIP_INIT_API(stream);

  return ihipStreamCreateWithFlags(stream, hipStreamDefault);
}

hipError_t hipStreamGetFlags(hipStream_t stream, unsigned int *flags) {
  HIP_INIT_API(stream, flags);

  amd::HostQueue* hostQueue = as_amd(reinterpret_cast<cl_command_queue>(stream))->asHostQueue();
  auto it = streamSet.find(hostQueue);

  if(flags != nullptr) {
    *flags = (it != streamSet.end()) ? hipStreamNonBlocking : hipStreamDefault;
  } else {
    return hipErrorInvalidValue;
  }

  return hipSuccess;
}

hipError_t hipStreamSynchronize(hipStream_t stream) {
  HIP_INIT_API(stream);

  amd::HostQueue* hostQueue;

  if (stream == nullptr) {
    hostQueue = hip::getNullStream();
  } else {
    hostQueue = as_amd(reinterpret_cast<cl_command_queue>(stream))->asHostQueue();
  }

  if (hostQueue == nullptr) {
    return hipErrorUnknown;
  }

  hostQueue->finish();

  return hipSuccess;
}

hipError_t hipStreamDestroy(hipStream_t stream) {
  HIP_INIT_API(stream);

  if (stream == nullptr) {
    return hipErrorInvalidResourceHandle;
  }

  amd::HostQueue* hostQueue = as_amd(reinterpret_cast<cl_command_queue>(stream))->asHostQueue();
  hostQueue->release();
  streamSet.erase(hostQueue);

  return hipSuccess;
}

hipError_t hipStreamWaitEvent(hipStream_t stream, hipEvent_t event, unsigned int flags) {
  HIP_INIT_API(stream, event, flags);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipStreamQuery(hipStream_t stream) {
  HIP_INIT_API(stream);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

hipError_t hipStreamAddCallback(hipStream_t stream, hipStreamCallback_t callback, void* userData,
                                unsigned int flags) {
  HIP_INIT_API(stream, callback, userData, flags);

  assert(0 && "Unimplemented");

  return hipErrorUnknown;
}

<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++98, c++03, c++11
// <vector>
//  vector.bool

// template <class... Args> reference emplace_back(Args&&... args);
// return type is 'reference' in C++17; 'void' before

#include <vector>
#include <cassert>
#include "test_macros.h"
#include "min_allocator.h"

int main()
{
    {
        typedef std::vector<bool> C;
        C c;
#if TEST_STD_VER > 14
        typedef C::reference Ref;
        Ref r1 = c.emplace_back();
        assert(c.size() == 1);
        assert(c.front() == false);
        r1 = true;
        assert(c.front() == true);
        r1 = false;
        Ref r2 = c.emplace_back(true);
        assert(c.size() == 2);
        assert(c.front() == false);
        assert(c.back() == true);
        r2 = false;
        assert(c.back() == false);
        r2 = true;
#else
        c.emplace_back();
        assert(c.size() == 1);
        assert(c.front() == false);
        c.emplace_back(true);
        assert(c.size() == 2);
        assert(c.front() == false);
        assert(c.back() == true);
#endif
        c.emplace_back(1 == 1);
        assert(c.size() == 3);
        assert(c.front() == false);
        assert(c[1] == true);
        assert(c.back() == true);
    }
    {
        typedef std::vector<bool, min_allocator<bool>> C;
        C c;

#if TEST_STD_VER > 14
        typedef C::reference Ref;
        Ref r1 = c.emplace_back();
        assert(c.size() == 1);
        assert(c.front() == false);
        r1 = true;
        assert(c.front() == true);
        r1 = false;
        Ref r2 = c.emplace_back(true);
        assert(c.size() == 2);
        assert(c.front() == false);
        assert(c.back() == true);
        r2 = false;
        assert(c.back() == false);
        r2 = true;
#else
        c.emplace_back();
        assert(c.size() == 1);
        assert(c.front() == false);
        c.emplace_back(true);
        assert(c.size() == 2);
        assert(c.front() == false);
        assert(c.back() == true);
#endif
        c.emplace_back(1 == 1);
        assert(c.size() == 3);
        assert(c.front() == false);
        assert(c[1] == true);
        assert(c.back() == true);
    }
}
<commit_msg>[libcxx] [test] Fix MSVC "warning C6326: Potential comparison of a constant with another constant".<commit_after>//===----------------------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is dual licensed under the MIT and the University of Illinois Open
// Source Licenses. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++98, c++03, c++11
// <vector>
//  vector.bool

// template <class... Args> reference emplace_back(Args&&... args);
// return type is 'reference' in C++17; 'void' before

#include <vector>
#include <cassert>
#include "test_macros.h"
#include "min_allocator.h"

int main()
{
    {
        typedef std::vector<bool> C;
        C c;
#if TEST_STD_VER > 14
        typedef C::reference Ref;
        Ref r1 = c.emplace_back();
        assert(c.size() == 1);
        assert(c.front() == false);
        r1 = true;
        assert(c.front() == true);
        r1 = false;
        Ref r2 = c.emplace_back(true);
        assert(c.size() == 2);
        assert(c.front() == false);
        assert(c.back() == true);
        r2 = false;
        assert(c.back() == false);
        r2 = true;
#else
        c.emplace_back();
        assert(c.size() == 1);
        assert(c.front() == false);
        c.emplace_back(true);
        assert(c.size() == 2);
        assert(c.front() == false);
        assert(c.back() == true);
#endif
        c.emplace_back(true);
        assert(c.size() == 3);
        assert(c.front() == false);
        assert(c[1] == true);
        assert(c.back() == true);
    }
    {
        typedef std::vector<bool, min_allocator<bool>> C;
        C c;

#if TEST_STD_VER > 14
        typedef C::reference Ref;
        Ref r1 = c.emplace_back();
        assert(c.size() == 1);
        assert(c.front() == false);
        r1 = true;
        assert(c.front() == true);
        r1 = false;
        Ref r2 = c.emplace_back(true);
        assert(c.size() == 2);
        assert(c.front() == false);
        assert(c.back() == true);
        r2 = false;
        assert(c.back() == false);
        r2 = true;
#else
        c.emplace_back();
        assert(c.size() == 1);
        assert(c.front() == false);
        c.emplace_back(true);
        assert(c.size() == 2);
        assert(c.front() == false);
        assert(c.back() == true);
#endif
        c.emplace_back(true);
        assert(c.size() == 3);
        assert(c.front() == false);
        assert(c[1] == true);
        assert(c.back() == true);
    }
}
<|endoftext|>


<commit_before>/****************************************************************************
 *   Copyright (C) 2013-2016 by Savoir-faire Linux                          *
 *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.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 General Public License      *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
 ***************************************************************************/
#include "lastusednumbermodel.h"
#include "call.h"
#include "uri.h"
#include "contactmethod.h"

struct ChainedContactMethod {
   ChainedContactMethod(ContactMethod* n) : m_pPrevious(nullptr),m_pNext(nullptr),m_pSelf(n){}
   ChainedContactMethod* m_pPrevious;
   ChainedContactMethod* m_pNext;
   ContactMethod*  m_pSelf;
};

class LastUsedNumberModelPrivate
{
public:
   LastUsedNumberModelPrivate();

   //Const
   constexpr static const int MAX_ITEM = 15;

   //Attributes
   ChainedContactMethod* m_pFirstNode;
   QHash<ContactMethod*,ChainedContactMethod*> m_hNumbers;
   bool m_IsValid;
   ChainedContactMethod* m_lLastNumbers[MAX_ITEM];
};

LastUsedNumberModelPrivate::LastUsedNumberModelPrivate():m_pFirstNode(nullptr),m_IsValid(false)
{}

LastUsedNumberModel::LastUsedNumberModel() : QAbstractListModel(),d_ptr(new LastUsedNumberModelPrivate())
{
   for (int i=0;i<LastUsedNumberModelPrivate::MAX_ITEM;i++)
      d_ptr->m_lLastNumbers[i] = nullptr;
}

LastUsedNumberModel::~LastUsedNumberModel()
{
   delete d_ptr;
}

LastUsedNumberModel& LastUsedNumberModel::instance()
{
    static auto instance = new LastUsedNumberModel();
    return *instance;
}

QHash<int,QByteArray> LastUsedNumberModel::roleNames() const
{
   static QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
   /*static bool initRoles = false;
   if (!initRoles) {
      initRoles = true;

   }*/
   return roles;
}

///Push 'call' phoneNumber on the top of the stack
void LastUsedNumberModel::addCall(Call* call)
{
   ContactMethod* number = call->peerContactMethod();
   ChainedContactMethod* node = d_ptr->m_hNumbers[number];
   if (!number || ( node && d_ptr->m_pFirstNode == node) ) {
      //TODO enable threaded numbers now
      return;
   }

   if (!node) {
      node = new ChainedContactMethod(number);
      d_ptr->m_hNumbers[number] = node;
   }
   else {
      if (node->m_pPrevious)
         node->m_pPrevious->m_pNext = node->m_pNext;
      if (node->m_pNext)
         node->m_pNext->m_pPrevious = node->m_pPrevious;
   }
   if (d_ptr->m_pFirstNode) {
      d_ptr->m_pFirstNode->m_pPrevious = node;
      node->m_pNext = d_ptr->m_pFirstNode;
   }
   d_ptr->m_pFirstNode = node;
   d_ptr->m_IsValid = false;
   emit layoutChanged();
}

QVariant LastUsedNumberModel::data( const QModelIndex& index, int role) const
{
   if (!index.isValid())
      return QVariant();
   if (!d_ptr->m_IsValid) {
      ChainedContactMethod* current = d_ptr->m_pFirstNode;
      for (int i=0;i<LastUsedNumberModelPrivate::MAX_ITEM;i++) { //Can only grow, no need to clear
         d_ptr->m_lLastNumbers[i] = current;
         current = current->m_pNext;
         if (!current)
            break;
      }
      d_ptr->m_IsValid = true;
   }
   switch (role) {
      case Qt::DisplayRole: {
         return d_ptr->m_lLastNumbers[index.row()]->m_pSelf->uri();
      }
   };
   return QVariant();
}

int LastUsedNumberModel::rowCount( const QModelIndex& parent) const
{
   if (parent.isValid())
      return 0;
   return d_ptr->m_hNumbers.size() < LastUsedNumberModelPrivate::MAX_ITEM?d_ptr->m_hNumbers.size():LastUsedNumberModelPrivate::MAX_ITEM;
}

Qt::ItemFlags LastUsedNumberModel::flags( const QModelIndex& index) const
{
   Q_UNUSED(index)
   return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
}

bool LastUsedNumberModel::setData( const QModelIndex& index, const QVariant &value, int role)
{
   Q_UNUSED(index)
   Q_UNUSED(value)
   Q_UNUSED(role)
   return false;
}
<commit_msg>lastusednumber: Fix uninitialized pointers<commit_after>/****************************************************************************
 *   Copyright (C) 2013-2016 by Savoir-faire Linux                          *
 *   Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.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 General Public License      *
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
 ***************************************************************************/
#include "lastusednumbermodel.h"
#include "call.h"
#include "uri.h"
#include "contactmethod.h"

struct ChainedContactMethod {
   ChainedContactMethod(ContactMethod* n) : m_pPrevious(nullptr),m_pNext(nullptr),m_pSelf(n){}
   ChainedContactMethod* m_pPrevious;
   ChainedContactMethod* m_pNext;
   ContactMethod*  m_pSelf;
};

class LastUsedNumberModelPrivate
{
public:
   LastUsedNumberModelPrivate();

   //Const
   constexpr static const int MAX_ITEM = 15;

   //Attributes
   ChainedContactMethod* m_pFirstNode;
   QHash<ContactMethod*,ChainedContactMethod*> m_hNumbers;
   bool m_IsValid;
   ChainedContactMethod* m_lLastNumbers[MAX_ITEM] {};
};

LastUsedNumberModelPrivate::LastUsedNumberModelPrivate():m_pFirstNode(nullptr),m_IsValid(false)
{}

LastUsedNumberModel::LastUsedNumberModel() : QAbstractListModel(),d_ptr(new LastUsedNumberModelPrivate())
{
   for (int i=0;i<LastUsedNumberModelPrivate::MAX_ITEM;i++)
      d_ptr->m_lLastNumbers[i] = nullptr;
}

LastUsedNumberModel::~LastUsedNumberModel()
{
   delete d_ptr;
}

LastUsedNumberModel& LastUsedNumberModel::instance()
{
    static auto instance = new LastUsedNumberModel();
    return *instance;
}

QHash<int,QByteArray> LastUsedNumberModel::roleNames() const
{
   static QHash<int, QByteArray> roles = QAbstractItemModel::roleNames();
   /*static bool initRoles = false;
   if (!initRoles) {
      initRoles = true;

   }*/
   return roles;
}

///Push 'call' phoneNumber on the top of the stack
void LastUsedNumberModel::addCall(Call* call)
{
   ContactMethod* number = call->peerContactMethod();
   ChainedContactMethod* node = d_ptr->m_hNumbers[number];
   if (!number || ( node && d_ptr->m_pFirstNode == node) ) {
      //TODO enable threaded numbers now
      return;
   }

   if (!node) {
      node = new ChainedContactMethod(number);
      d_ptr->m_hNumbers[number] = node;
   }
   else {
      if (node->m_pPrevious)
         node->m_pPrevious->m_pNext = node->m_pNext;
      if (node->m_pNext)
         node->m_pNext->m_pPrevious = node->m_pPrevious;
   }
   if (d_ptr->m_pFirstNode) {
      d_ptr->m_pFirstNode->m_pPrevious = node;
      node->m_pNext = d_ptr->m_pFirstNode;
   }
   d_ptr->m_pFirstNode = node;
   d_ptr->m_IsValid = false;
   emit layoutChanged();
}

QVariant LastUsedNumberModel::data( const QModelIndex& index, int role) const
{
   if (!index.isValid())
      return QVariant();
   if (!d_ptr->m_IsValid) {
      ChainedContactMethod* current = d_ptr->m_pFirstNode;
      for (int i=0;i<LastUsedNumberModelPrivate::MAX_ITEM;i++) { //Can only grow, no need to clear
         d_ptr->m_lLastNumbers[i] = current;
         current = current->m_pNext;
         if (!current)
            break;
      }
      d_ptr->m_IsValid = true;
   }
   switch (role) {
      case Qt::DisplayRole: {
         return d_ptr->m_lLastNumbers[index.row()]->m_pSelf->uri();
      }
   };
   return QVariant();
}

int LastUsedNumberModel::rowCount( const QModelIndex& parent) const
{
   if (parent.isValid())
      return 0;
   return d_ptr->m_hNumbers.size() < LastUsedNumberModelPrivate::MAX_ITEM?d_ptr->m_hNumbers.size():LastUsedNumberModelPrivate::MAX_ITEM;
}

Qt::ItemFlags LastUsedNumberModel::flags( const QModelIndex& index) const
{
   Q_UNUSED(index)
   return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
}

bool LastUsedNumberModel::setData( const QModelIndex& index, const QVariant &value, int role)
{
   Q_UNUSED(index)
   Q_UNUSED(value)
   Q_UNUSED(role)
   return false;
}
<|endoftext|>


<commit_before>#include "stable.h"

#include "SoundBuffer.h"
#include "WtsAudio.h"

#include <cmath>

#include <sndfile.hh>

using namespace WTS;

SoundBuffer::SoundBuffer(const QString& name)
    : m_name(name)
    , m_saved(true)
    , m_writePos(0)
    , m_readPos(0)
    , m_normGain(1)
    , m_gain(1)
{
    setRange(0,0);
}

SoundBuffer::SoundBuffer(qint64 sampleCount, const QString& name)
    : m_name(name)
    , m_saved(true)
    , m_data(sampleCount, 0)
    , m_writePos(0)
    , m_readPos(0)
    , m_normGain(1)
    , m_gain(1)
{
    setRange(0,sampleCount);
}

SoundBuffer::SoundBuffer(const QString& name, const SoundBuffer& other, qint64 sampleCount)
    : m_name(name)
    , m_saved(false)
    , m_data(other.m_data)
    , m_writePos(0)
    , m_readPos(0)
    , m_normGain(1)
    , m_gain(1)
{
    if (sampleCount && sampleCount != other.sampleCount())
        m_data.resize(sampleCount);
    setRange(0,sampleCount);
}

SoundBuffer& SoundBuffer::operator= (const SoundBuffer& other)
{
    m_data = other.m_data;
    m_name = other.m_name;
    m_saved = other.m_saved;
    m_writePos = 0;
    m_readPos = 0;
    m_range[0] = other.m_range[0];
    m_range[1] = other.m_range[1];
    m_normGain = other.m_normGain;
    m_gain = other.m_gain;
    return *this;
}

void SoundBuffer::save( const QDir& dir )
{
    QString path = dir.filePath( makeFileName( m_name ) );

    if (m_savedAs != path) {
        QFileInfo fi(m_savedAs);
        if (fi.exists()) {
            if (m_saved && fi.dir().rename( m_savedAs, path )) {
                qDebug() << "Renamed" << m_savedAs << "to" << path;
                m_savedAs = path;
                return;
            } else
                fi.dir().remove( fi.fileName() );
        }
    }

    if (m_saved)
        return;

    qDebug() << "Save sample to" << path;
    { // block to ensure file is closed by the moment we ask its modification time
        SndfileHandle snd(qPrintable(path),SFM_WRITE,
                SF_FORMAT_WAV | SF_FORMAT_FLOAT,
                1, // channel
                WtsAudio::samplingRate());

        snd.writef(m_data.data(),m_data.size());
    }
    m_timestamp = QFileInfo(path).lastModified();
    m_saved = true;
    m_savedAs = path;
}

void SoundBuffer::load( const QDir& dir )
{
    QString path = dir.filePath( makeFileName( m_name ) );

    qDebug() << "loading sample from" << path;

    if (QFile(path).exists()) {
        SndfileHandle snd(qPrintable(path));
        m_data.resize(snd.frames());
        snd.readf(m_data.data(),m_data.size());
        m_saved = true;
        m_savedAs = path;
    }

    m_readPos = 0;
    m_writePos = 0;
    m_timestamp = QFileInfo(path).lastModified();
}

bool SoundBuffer::maybeReload( const QDir& dir )
{
    QString path = dir.filePath( makeFileName( m_name ) );

    if (QFileInfo(path).lastModified() > m_timestamp) {
        qDebug() << "Sample " << m_name << " has changed on disk";

        qint64 old_length = m_data.size();

        load(dir);
        /*
         * if length has changed - select all
         */
        if (m_data.size() != old_length) {
            m_range[0] = 0;
            m_range[1] = m_data.size()-1;
        }
        return true;
    } else
        return false;
}

float* SoundBuffer::floatAt(qint64 pos)
{
    return m_data.data() + pos;
}

const float* SoundBuffer::floatAt(qint64 pos) const
{
    return m_data.constData() + pos;
}

void SoundBuffer::paste(const SoundBuffer * other)
{
    qint64 pasteSize = std::min(sampleCount() - m_writePos, other->sampleCount());
    qCopy( other->m_data.begin(), other->m_data.begin() + pasteSize, m_data.begin() );
    m_writePos += pasteSize;
}

float* SoundBuffer::chunkToWrite(qint64& size) {
    size = std::min(size, sampleCount() - m_writePos);
    float * chunk = floatAt(m_writePos);
    m_writePos += size;
    return chunk;
}

qint64 SoundBuffer::duration() const
{
    return WtsAudio::sampleCountToMs(m_data.size());
}

void SoundBuffer::initGains()
{
    float peak = 0.0;
    foreach(float v, m_data) {
        if (fabs(v) > peak) {
            peak = v;
        }
    }
    m_normGain = 1.0 / peak;
    m_gain = peak;
    // What?
}

float WTS::SoundBuffer::draw(QPixmap& surface, bool recording, float scaleMax)
{
    QPainter painter(&surface);
    painter.setPen(QColor(0,0,0,100));
    painter.fillRect(0,0,surface.width(),surface.height(), color() );
    int midY = surface.height()/2;

    qint64 stride = 1;
    const float * val = floatAt(0);
    qint64 lineCount =
            std::min((qint64)surface.width(),
                     recording ? m_writePos : sampleCount());
    QVector<float> Y(lineCount, 0.0);

    if (recording) {
        val = floatAt(m_writePos - lineCount);
    } else {
        // show the whole thing
        stride = sampleCount() / lineCount;
    }

    for(int x = 0; x<lineCount; ++x) {
        Y[x] = val[x*stride];
        for(int i=1; i<stride; ++i) {
            Y[x] = std::max(Y[x], (float)fabs(val[x*stride+i]));
        }
        scaleMax = std::max(Y[x],scaleMax);
    }

    for(int x = 0; x<lineCount; ++x) {
        int y1 = midY + (0.45 * (Y[x]/scaleMax) * (float)surface.height());
        int y2 = midY - (0.45 * (Y[x]/scaleMax) * (float)surface.height());
        painter.drawLine(x, y1, x, y2);
    }

    painter.drawLine(lineCount, midY, surface.width(), midY);
    return scaleMax;
}

QString WTS::SoundBuffer::makeFileName(const QString &name)
{
    QString badsyms = "[^a-z0-9_]+";
    QRegExp lead( "^"+ badsyms );
    QRegExp tail( badsyms + "$" );
    QRegExp mid(badsyms);
    QString result = name;
    result.remove(lead).remove(tail).replace(mid,"_").append(".wav");
    return result;
}
<commit_msg>don't filter out caps from sample names when making a file name<commit_after>#include "stable.h"

#include "SoundBuffer.h"
#include "WtsAudio.h"

#include <cmath>

#include <sndfile.hh>

using namespace WTS;

SoundBuffer::SoundBuffer(const QString& name)
    : m_name(name)
    , m_saved(true)
    , m_writePos(0)
    , m_readPos(0)
    , m_normGain(1)
    , m_gain(1)
{
    setRange(0,0);
}

SoundBuffer::SoundBuffer(qint64 sampleCount, const QString& name)
    : m_name(name)
    , m_saved(true)
    , m_data(sampleCount, 0)
    , m_writePos(0)
    , m_readPos(0)
    , m_normGain(1)
    , m_gain(1)
{
    setRange(0,sampleCount);
}

SoundBuffer::SoundBuffer(const QString& name, const SoundBuffer& other, qint64 sampleCount)
    : m_name(name)
    , m_saved(false)
    , m_data(other.m_data)
    , m_writePos(0)
    , m_readPos(0)
    , m_normGain(1)
    , m_gain(1)
{
    if (sampleCount && sampleCount != other.sampleCount())
        m_data.resize(sampleCount);
    setRange(0,sampleCount);
}

SoundBuffer& SoundBuffer::operator= (const SoundBuffer& other)
{
    m_data = other.m_data;
    m_name = other.m_name;
    m_saved = other.m_saved;
    m_writePos = 0;
    m_readPos = 0;
    m_range[0] = other.m_range[0];
    m_range[1] = other.m_range[1];
    m_normGain = other.m_normGain;
    m_gain = other.m_gain;
    return *this;
}

void SoundBuffer::save( const QDir& dir )
{
    QString path = dir.filePath( makeFileName( m_name ) );

    if (m_savedAs != path) {
        QFileInfo fi(m_savedAs);
        if (fi.exists()) {
            if (m_saved && fi.dir().rename( m_savedAs, path )) {
                qDebug() << "Renamed" << m_savedAs << "to" << path;
                m_savedAs = path;
                return;
            } else
                fi.dir().remove( fi.fileName() );
        }
    }

    if (m_saved)
        return;

    qDebug() << "Save sample to" << path;
    { // block to ensure file is closed by the moment we ask its modification time
        SndfileHandle snd(qPrintable(path),SFM_WRITE,
                SF_FORMAT_WAV | SF_FORMAT_FLOAT,
                1, // channel
                WtsAudio::samplingRate());

        snd.writef(m_data.data(),m_data.size());
    }
    m_timestamp = QFileInfo(path).lastModified();
    m_saved = true;
    m_savedAs = path;
}

void SoundBuffer::load( const QDir& dir )
{
    QString path = dir.filePath( makeFileName( m_name ) );

    qDebug() << "loading sample from" << path;

    if (QFile(path).exists()) {
        SndfileHandle snd(qPrintable(path));
        m_data.resize(snd.frames());
        snd.readf(m_data.data(),m_data.size());
        m_saved = true;
        m_savedAs = path;
    }

    m_readPos = 0;
    m_writePos = 0;
    m_timestamp = QFileInfo(path).lastModified();
}

bool SoundBuffer::maybeReload( const QDir& dir )
{
    QString path = dir.filePath( makeFileName( m_name ) );

    if (QFileInfo(path).lastModified() > m_timestamp) {
        qDebug() << "Sample " << m_name << " has changed on disk";

        qint64 old_length = m_data.size();

        load(dir);
        /*
         * if length has changed - select all
         */
        if (m_data.size() != old_length) {
            m_range[0] = 0;
            m_range[1] = m_data.size()-1;
        }
        return true;
    } else
        return false;
}

float* SoundBuffer::floatAt(qint64 pos)
{
    return m_data.data() + pos;
}

const float* SoundBuffer::floatAt(qint64 pos) const
{
    return m_data.constData() + pos;
}

void SoundBuffer::paste(const SoundBuffer * other)
{
    qint64 pasteSize = std::min(sampleCount() - m_writePos, other->sampleCount());
    qCopy( other->m_data.begin(), other->m_data.begin() + pasteSize, m_data.begin() );
    m_writePos += pasteSize;
}

float* SoundBuffer::chunkToWrite(qint64& size) {
    size = std::min(size, sampleCount() - m_writePos);
    float * chunk = floatAt(m_writePos);
    m_writePos += size;
    return chunk;
}

qint64 SoundBuffer::duration() const
{
    return WtsAudio::sampleCountToMs(m_data.size());
}

void SoundBuffer::initGains()
{
    float peak = 0.0;
    foreach(float v, m_data) {
        if (fabs(v) > peak) {
            peak = v;
        }
    }
    m_normGain = 1.0 / peak;
    m_gain = peak;
    // What?
}

float WTS::SoundBuffer::draw(QPixmap& surface, bool recording, float scaleMax)
{
    QPainter painter(&surface);
    painter.setPen(QColor(0,0,0,100));
    painter.fillRect(0,0,surface.width(),surface.height(), color() );
    int midY = surface.height()/2;

    qint64 stride = 1;
    const float * val = floatAt(0);
    qint64 lineCount =
            std::min((qint64)surface.width(),
                     recording ? m_writePos : sampleCount());
    QVector<float> Y(lineCount, 0.0);

    if (recording) {
        val = floatAt(m_writePos - lineCount);
    } else {
        // show the whole thing
        stride = sampleCount() / lineCount;
    }

    for(int x = 0; x<lineCount; ++x) {
        Y[x] = val[x*stride];
        for(int i=1; i<stride; ++i) {
            Y[x] = std::max(Y[x], (float)fabs(val[x*stride+i]));
        }
        scaleMax = std::max(Y[x],scaleMax);
    }

    for(int x = 0; x<lineCount; ++x) {
        int y1 = midY + (0.45 * (Y[x]/scaleMax) * (float)surface.height());
        int y2 = midY - (0.45 * (Y[x]/scaleMax) * (float)surface.height());
        painter.drawLine(x, y1, x, y2);
    }

    painter.drawLine(lineCount, midY, surface.width(), midY);
    return scaleMax;
}

QString WTS::SoundBuffer::makeFileName(const QString &name)
{
    QString badsyms = "[^a-z0-9_]+";
    QRegExp lead( "^"+ badsyms, Qt::CaseInsensitive );
    QRegExp tail( badsyms + "$", Qt::CaseInsensitive );
    QRegExp  mid( badsyms, Qt::CaseInsensitive );
    QString result = name;
    result.remove(lead).remove(tail).replace(mid,"_").append(".wav");
    return result;
}
<|endoftext|>


<commit_before>#pragma once

#include <boost/hana/equal.hpp>
#include <boost/hana/for_each.hpp>
#include <boost/hana/size.hpp>

#include <functional>
#include <memory>
#include <string>
#include <utility>

#include "all_type_variant.hpp"
#include "utils/assert.hpp"

#include "storage/dictionary_column.hpp"
#include "storage/reference_column.hpp"
#include "storage/value_column.hpp"

namespace opossum {

namespace hana = boost::hana;

/**
 * Resolves a type string by creating an instance of a templated class and
 * returning it as a unique_ptr of its non-templated base class.
 *
 * @param type is a string representation of any of the supported column types
 * @param args is a list of constructor arguments
 *
 *
 * Example:
 *
 *   class BaseImpl {
 *    public:
 *     virtual void execute() = 0;
 *   };
 *
 *   template <typename T>
 *   class Impl : public BaseImpl {
 *    public:
 *     Impl(int var) : _var{var} { ... }
 *
 *     void execute() override { ... }
 *   };
 *
 *   constexpr auto var = 12;
 *   auto impl = make_unique_by_column_type<BaseImpl, Impl>("string", var);
 *   impl->execute();
 */
template <class Base, template <typename...> class Impl, class... TemplateArgs, typename... ConstructorArgs>
std::unique_ptr<Base> make_unique_by_column_type(const std::string& type, ConstructorArgs&&... args) {
  std::unique_ptr<Base> ret = nullptr;
  hana::for_each(column_types, [&](auto x) {
    if (std::string(hana::first(x)) == type) {
      // The + before hana::second - which returns a reference - converts its return value
      // into a value so that we can access ::type
      using ColumnType = typename decltype(+hana::second(x))::type;
      ret = std::make_unique<Impl<ColumnType, TemplateArgs...>>(std::forward<ConstructorArgs>(args)...);
      return;
    }
  });
  DebugAssert(static_cast<bool>(ret), "unknown type " + type);
  return ret;
}

/**
 * Resolves two type strings by creating an instance of a templated class and
 * returning it as a unique_ptr of its non-templated base class.
 * It does the same as make_unique_by_column_type but with two type strings.
 *
 * @param type1 is a string representation of any of the supported column types
 * @param type2 is a string representation of any of the supported column types
 * @param args is a list of constructor arguments
 *
 * Note: We need to pass parameter packs explicitly for GCC due to the following bug:
 *       http://stackoverflow.com/questions/41769851/gcc-causes-segfault-for-lambda-captured-parameter-pack
 */
template <class Base, template <typename...> class Impl, class... TemplateArgs, typename... ConstructorArgs>
std::unique_ptr<Base> make_unique_by_column_types(const std::string& type1, const std::string& type2,
                                                  ConstructorArgs&&... args) {
  std::unique_ptr<Base> ret = nullptr;
  hana::for_each(column_types, [&ret, &type1, &type2, &args...](auto x) {
    if (std::string(hana::first(x)) == type1) {
      hana::for_each(column_types, [&ret, &type2, &args...](auto y) {
        if (std::string(hana::first(y)) == type2) {
          using ColumnType1 = typename decltype(+hana::second(x))::type;
          using ColumnType2 = typename decltype(+hana::second(y))::type;
          ret =
              std::make_unique<Impl<ColumnType1, ColumnType2, TemplateArgs...>>(std::forward<ConstructorArgs>(args)...);
          return;
        }
      });
      return;
    }
  });
  DebugAssert(static_cast<bool>(ret), "unknown type " + type1 + " or " + type2);
  return ret;
}

/**
 * Convenience function. Calls make_unique_by_column_type and casts the result into a shared_ptr.
 */
template <class Base, template <typename...> class impl, class... TemplateArgs, class... ConstructorArgs>
std::shared_ptr<Base> make_shared_by_column_type(const std::string& type, ConstructorArgs&&... args) {
  return make_unique_by_column_type<Base, impl, TemplateArgs...>(type, std::forward<ConstructorArgs>(args)...);
}

/**
 * Resolves a type string by passing a hana::type object on to a generic lambda
 *
 * @param type_string is a string representation of any of the supported column types
 * @param func is a generic lambda or similar accepting a hana::type object
 *
 *
 * Note on hana::type (taken from Boost.Hana documentation):
 *
 * For subtle reasons having to do with ADL, the actual representation of hana::type is
 * implementation-defined. In particular, hana::type may be a dependent type, so one
 * should not attempt to do pattern matching on it. However, one can assume that hana::type
 * inherits from hana::basic_type, which can be useful when declaring overloaded functions.
 *
 * This means that we need to use hana::basic_type as a parameter in methods so that the
 * underlying type can be deduced from the object.
 *
 *
 * Note on generic lambdas (taken from paragraph 5.1.2/5 of the C++14 Standard Draft n3690):
 *
 * For a generic lambda, the closure type has a public inline function call operator member template (14.5.2)
 * whose template-parameter-list consists of one invented type template-parameter for each occurrence of auto
 * in the lambda’s parameter-declaration-clause, in order of appearance. Example:
 *
 *   auto lambda = [] (auto a) { return a; };
 *
 *   class // unnamed {
 *    public:
 *     template<typename T>
 *     auto operator()(T a) const { return a; }
 *   };
 *
 *
 * Example:
 *
 *   template <typename T>
 *   process_variant(const T& var);
 *
 *   template <typename T>
 *   process_type(hana::basic_type<T> type);  // note: parameter type needs to be hana::basic_type not hana::type!
 *
 *   resolve_data_type(type_string, [&](auto type) {
 *     using Type = typename decltype(type)::type;
 *     const auto var = type_cast<Type>(variant_from_elsewhere);
 *     process_variant(var);
 *
 *     process_type(type);
 *   });
 */
template <typename Functor>
void resolve_data_type(const std::string& type_string, const Functor& func) {
  hana::for_each(column_types, [&](auto x) {
    if (std::string(hana::first(x)) == type_string) {
      // The + before hana::second - which returns a reference - converts its return value into a value
      func(+hana::second(x));
      return;
    }
  });
}

/**
 * Given a BaseColumn and its known DataType, resolve the column implementation and call the lambda
 *
 * @param func is a generic lambda or similar accepting a reference to a specialized column (value, dictionary,
 * reference)
 *
 *
 * Example:
 *
 *   template <typename T>
 *   process_column(ValueColumn<T>& column);
 *
 *   template <typename T>
 *   process_column(DictionaryColumn<T>& column);
 *
 *   process_column(ReferenceColumn& column);
 *
 *   resolve_column_type<T>(base_column, [&](auto& typed_column) {
 *     process_column(typed_column);
 *   });
 */
template <typename DataType, typename Functor>
void resolve_column_type(BaseColumn& column, const Functor& func) {
  if (auto value_column = dynamic_cast<ValueColumn<DataType>*>(&column)) {
    func(*value_column);
  } else if (auto dict_column = dynamic_cast<DictionaryColumn<DataType>*>(&column)) {
    func(*dict_column);
  } else if (auto ref_column = dynamic_cast<ReferenceColumn*>(&column)) {
    func(*ref_column);
  } else {
    Fail("Unrecognized column type encountered.");
  }
}

/**
 * Resolves a type string by passing a hana::type object and the downcasted column on to a generic lambda
 *
 * @param type_string is a string representation of any of the supported column types
 * @param func is a generic lambda or similar accepting two parameters: a hana::type object and
 *   a reference to a specialized column (value, dictionary, reference)
 *
 *
 * Example:
 *
 *   template <typename T>
 *   process_column(hana::basic_type<T> type, ValueColumn<T>& column);
 *
 *   template <typename T>
 *   process_column(hana::basic_type<T> type, DictionaryColumn<T>& column);
 *
 *   template <typename T>
 *   process_column(hana::basic_type<T> type, ReferenceColumn& column);
 *
 *   resolve_data_and_column_type(column_type, base_column, [&](auto type, auto& typed_column) {
 *     process_column(type, typed_column);
 *   });
 */
template <typename Functor>
void resolve_data_and_column_type(const std::string& type_string, BaseColumn& column, const Functor& func) {
  resolve_data_type(type_string, [&](auto data_type) {
    using DataType = typename decltype(data_type)::type;

    resolve_column_type<DataType>(column, [&](auto& typed_column) { func(data_type, typed_column); });
  });
}

/**
 * This function returns the name of an Opossum datatype based on the definition in column_types.
 */
template <typename T>
std::string type_string_from_type() {
  const auto func = [](std::string s, auto type_tuple) {
    // a matching type was found before
    if (s.size() != 0) {
      return s;
    }

    // check whether T is one of the Opossum datatypes
    if (hana::type_c<T> == hana::second(type_tuple)) {
      return std::string{hana::first(type_tuple)};
    }

    return std::string{};
  };

  const auto type_string = hana::fold_left(column_types, std::string{}, func);
  Assert(type_string.size() > 0, "Trying to parse unknown type which is not part of AllTypeVariant");

  return type_string;
}

/**
 * This function returns the name of an Opossum datatype based on the definition in column_types.
 */
inline std::string type_string_from_all_type_variant(const AllTypeVariant& all_type_variant) {
  // Special case for NullValue data type
  if (all_type_variant.which() == 0) {
    return "None";
  }

  // iterate over column_types
  int column_types_index = 1;

  auto func = [all_type_variant, &column_types_index](std::string s, auto type_tuple) {
    // a matching type was found before
    if (s.size() != 0) {
      return s;
    }

    if (all_type_variant.which() == column_types_index) {
      column_types_index++;
      return std::string{hana::first(type_tuple)};
    }

    column_types_index++;
    return std::string{};
  };

  return hana::fold_left(column_types, std::string{}, func);
}

}  // namespace opossum
<commit_msg>Allow resolve_column_type to use const (#350)<commit_after>#pragma once

#include <boost/hana/equal.hpp>
#include <boost/hana/for_each.hpp>
#include <boost/hana/size.hpp>

#include <functional>
#include <memory>
#include <string>
#include <utility>

#include "all_type_variant.hpp"
#include "utils/assert.hpp"

#include "storage/dictionary_column.hpp"
#include "storage/reference_column.hpp"
#include "storage/value_column.hpp"

namespace opossum {

namespace hana = boost::hana;

/**
 * Resolves a type string by creating an instance of a templated class and
 * returning it as a unique_ptr of its non-templated base class.
 *
 * @param type is a string representation of any of the supported column types
 * @param args is a list of constructor arguments
 *
 *
 * Example:
 *
 *   class BaseImpl {
 *    public:
 *     virtual void execute() = 0;
 *   };
 *
 *   template <typename T>
 *   class Impl : public BaseImpl {
 *    public:
 *     Impl(int var) : _var{var} { ... }
 *
 *     void execute() override { ... }
 *   };
 *
 *   constexpr auto var = 12;
 *   auto impl = make_unique_by_column_type<BaseImpl, Impl>("string", var);
 *   impl->execute();
 */
template <class Base, template <typename...> class Impl, class... TemplateArgs, typename... ConstructorArgs>
std::unique_ptr<Base> make_unique_by_column_type(const std::string& type, ConstructorArgs&&... args) {
  std::unique_ptr<Base> ret = nullptr;
  hana::for_each(column_types, [&](auto x) {
    if (std::string(hana::first(x)) == type) {
      // The + before hana::second - which returns a reference - converts its return value
      // into a value so that we can access ::type
      using ColumnType = typename decltype(+hana::second(x))::type;
      ret = std::make_unique<Impl<ColumnType, TemplateArgs...>>(std::forward<ConstructorArgs>(args)...);
      return;
    }
  });
  DebugAssert(static_cast<bool>(ret), "unknown type " + type);
  return ret;
}

/**
 * Resolves two type strings by creating an instance of a templated class and
 * returning it as a unique_ptr of its non-templated base class.
 * It does the same as make_unique_by_column_type but with two type strings.
 *
 * @param type1 is a string representation of any of the supported column types
 * @param type2 is a string representation of any of the supported column types
 * @param args is a list of constructor arguments
 *
 * Note: We need to pass parameter packs explicitly for GCC due to the following bug:
 *       http://stackoverflow.com/questions/41769851/gcc-causes-segfault-for-lambda-captured-parameter-pack
 */
template <class Base, template <typename...> class Impl, class... TemplateArgs, typename... ConstructorArgs>
std::unique_ptr<Base> make_unique_by_column_types(const std::string& type1, const std::string& type2,
                                                  ConstructorArgs&&... args) {
  std::unique_ptr<Base> ret = nullptr;
  hana::for_each(column_types, [&ret, &type1, &type2, &args...](auto x) {
    if (std::string(hana::first(x)) == type1) {
      hana::for_each(column_types, [&ret, &type2, &args...](auto y) {
        if (std::string(hana::first(y)) == type2) {
          using ColumnType1 = typename decltype(+hana::second(x))::type;
          using ColumnType2 = typename decltype(+hana::second(y))::type;
          ret =
              std::make_unique<Impl<ColumnType1, ColumnType2, TemplateArgs...>>(std::forward<ConstructorArgs>(args)...);
          return;
        }
      });
      return;
    }
  });
  DebugAssert(static_cast<bool>(ret), "unknown type " + type1 + " or " + type2);
  return ret;
}

/**
 * Convenience function. Calls make_unique_by_column_type and casts the result into a shared_ptr.
 */
template <class Base, template <typename...> class impl, class... TemplateArgs, class... ConstructorArgs>
std::shared_ptr<Base> make_shared_by_column_type(const std::string& type, ConstructorArgs&&... args) {
  return make_unique_by_column_type<Base, impl, TemplateArgs...>(type, std::forward<ConstructorArgs>(args)...);
}

/**
 * Resolves a type string by passing a hana::type object on to a generic lambda
 *
 * @param type_string is a string representation of any of the supported column types
 * @param func is a generic lambda or similar accepting a hana::type object
 *
 *
 * Note on hana::type (taken from Boost.Hana documentation):
 *
 * For subtle reasons having to do with ADL, the actual representation of hana::type is
 * implementation-defined. In particular, hana::type may be a dependent type, so one
 * should not attempt to do pattern matching on it. However, one can assume that hana::type
 * inherits from hana::basic_type, which can be useful when declaring overloaded functions.
 *
 * This means that we need to use hana::basic_type as a parameter in methods so that the
 * underlying type can be deduced from the object.
 *
 *
 * Note on generic lambdas (taken from paragraph 5.1.2/5 of the C++14 Standard Draft n3690):
 *
 * For a generic lambda, the closure type has a public inline function call operator member template (14.5.2)
 * whose template-parameter-list consists of one invented type template-parameter for each occurrence of auto
 * in the lambda’s parameter-declaration-clause, in order of appearance. Example:
 *
 *   auto lambda = [] (auto a) { return a; };
 *
 *   class // unnamed {
 *    public:
 *     template<typename T>
 *     auto operator()(T a) const { return a; }
 *   };
 *
 *
 * Example:
 *
 *   template <typename T>
 *   process_variant(const T& var);
 *
 *   template <typename T>
 *   process_type(hana::basic_type<T> type);  // note: parameter type needs to be hana::basic_type not hana::type!
 *
 *   resolve_data_type(type_string, [&](auto type) {
 *     using Type = typename decltype(type)::type;
 *     const auto var = type_cast<Type>(variant_from_elsewhere);
 *     process_variant(var);
 *
 *     process_type(type);
 *   });
 */
template <typename Functor>
void resolve_data_type(const std::string& type_string, const Functor& func) {
  hana::for_each(column_types, [&](auto x) {
    if (std::string(hana::first(x)) == type_string) {
      // The + before hana::second - which returns a reference - converts its return value into a value
      func(+hana::second(x));
      return;
    }
  });
}

/**
 * Given a BaseColumn and its known DataType, resolve the column implementation and call the lambda
 *
 * @param func is a generic lambda or similar accepting a reference to a specialized column (value, dictionary,
 * reference)
 *
 *
 * Example:
 *
 *   template <typename T>
 *   void process_column(ValueColumn<T>& column);
 *
 *   template <typename T>
 *   void process_column(DictionaryColumn<T>& column);
 *
 *   void process_column(ReferenceColumn& column);
 *
 *   resolve_column_type<T>(base_column, [&](auto& typed_column) {
 *     process_column(typed_column);
 *   });
 */
template <typename In, typename Out>
using Const_out_if_const_in = std::conditional_t<std::is_const<In>::value, const Out, Out>;

template <typename DataType, typename BaseColumnType, typename Functor>
// BaseColumnType allows column to be const and non-const
std::enable_if_t<std::is_same<BaseColumn, std::remove_const_t<BaseColumnType>>::value>
    /*void*/ resolve_column_type(BaseColumnType& column, const Functor& func) {
  using ValueColumnPtr = Const_out_if_const_in<BaseColumnType, ValueColumn<DataType>*>;
  using DictionaryColumnPtr = Const_out_if_const_in<BaseColumnType, DictionaryColumn<DataType>*>;
  using ReferenceColumnPtr = Const_out_if_const_in<BaseColumnType, ReferenceColumn*>;

  if (auto value_column = dynamic_cast<ValueColumnPtr>(&column)) {
    func(*value_column);
  } else if (auto dict_column = dynamic_cast<DictionaryColumnPtr>(&column)) {
    func(*dict_column);
  } else if (auto ref_column = dynamic_cast<ReferenceColumnPtr>(&column)) {
    func(*ref_column);
  } else {
    Fail("Unrecognized column type encountered.");
  }
}

/**
 * Resolves a type string by passing a hana::type object and the downcasted column on to a generic lambda
 *
 * @param type_string is a string representation of any of the supported column types
 * @param func is a generic lambda or similar accepting two parameters: a hana::type object and
 *   a reference to a specialized column (value, dictionary, reference)
 *
 *
 * Example:
 *
 *   template <typename T>
 *   void process_column(hana::basic_type<T> type, ValueColumn<T>& column);
 *
 *   template <typename T>
 *   void process_column(hana::basic_type<T> type, DictionaryColumn<T>& column);
 *
 *   template <typename T>
 *   void process_column(hana::basic_type<T> type, ReferenceColumn& column);
 *
 *   resolve_data_and_column_type(column_type, base_column, [&](auto type, auto& typed_column) {
 *     process_column(type, typed_column);
 *   });
 */
template <typename Functor, typename BaseColumnT>  // BaseColumnT allows column to be const and non-const
std::enable_if_t<std::is_same<BaseColumn, std::remove_const_t<BaseColumnT>>::value>
    /*void*/ resolve_data_and_column_type(const std::string& type_string, BaseColumnT& column, const Functor& func) {
  resolve_data_type(type_string, [&](auto data_type) {
    using DataType = typename decltype(data_type)::type;

    resolve_column_type<DataType>(column, [&](auto& typed_column) { func(data_type, typed_column); });
  });
}

/**
 * This function returns the name of an Opossum datatype based on the definition in column_types.
 */
template <typename T>
std::string type_string_from_type() {
  const auto func = [](std::string s, auto type_tuple) {
    // a matching type was found before
    if (s.size() != 0) {
      return s;
    }

    // check whether T is one of the Opossum datatypes
    if (hana::type_c<T> == hana::second(type_tuple)) {
      return std::string{hana::first(type_tuple)};
    }

    return std::string{};
  };

  const auto type_string = hana::fold_left(column_types, std::string{}, func);
  Assert(type_string.size() > 0, "Trying to parse unknown type which is not part of AllTypeVariant");

  return type_string;
}

/**
 * This function returns the name of an Opossum datatype based on the definition in column_types.
 */
inline std::string type_string_from_all_type_variant(const AllTypeVariant& all_type_variant) {
  // Special case for NullValue data type
  if (all_type_variant.which() == 0) {
    return "None";
  }

  // iterate over column_types
  int column_types_index = 1;

  auto func = [all_type_variant, &column_types_index](std::string s, auto type_tuple) {
    // a matching type was found before
    if (s.size() != 0) {
      return s;
    }

    if (all_type_variant.which() == column_types_index) {
      column_types_index++;
      return std::string{hana::first(type_tuple)};
    }

    column_types_index++;
    return std::string{};
  };

  return hana::fold_left(column_types, std::string{}, func);
}

}  // namespace opossum
<|endoftext|>


<commit_before>#include "HttpParser.h"

#include "http_parser/http_parser.h"
#include <memory>

HttpParser::Status::Status(void* parser)
	: _parser(parser)
{
}

unsigned HttpParser::Status::method() const
{
	return static_cast<http_parser*>(_parser)->method;
}

unsigned HttpParser::Status::code() const
{
	return static_cast<http_parser*>(_parser)->status_code;
}

class HttpParser::Impl
{
public:
	Impl()
		: _parser(new http_parser)
		, _settings{0}
	{
		http_parser_init(_parser.get(), HTTP_REQUEST);
	}

	bool parseBuffer(const char* buffer, unsigned size)
	{
		int parsedSize = http_parser_execute(_parser.get(), &_settings, buffer, size);
		return parsedSize == size;
	}

//callbacks
public:
	void setOnMessageBegin(const callback& fun)
	{
		static auto wrapper = fun;
		_settings.on_message_begin = [](http_parser*){ return wrapper(); };
	}

	void setOnMessageComplete(const callback& fun)
	{
		static auto wrapper = fun;
		_settings.on_message_complete = [](http_parser*){ return wrapper(); };
	}

	void setOnUrl(const dataCallback& fun)
	{
		static auto wrapper = fun;
		_settings.on_url = [](http_parser*, const char* buff, size_t len){ return wrapper(buff, len); };
	}

	void setOnHeaderField(const dataCallback& fun)
	{
		static auto wrapper = fun;
		_settings.on_header_field = [](http_parser*, const char* buff, size_t len){ return wrapper(buff, len); };
	}

	void setOnHeaderValue(const dataCallback& fun)
	{
		static auto wrapper = fun;
		_settings.on_header_value = [](http_parser*, const char* buff, size_t len){ return wrapper(buff, len); };
	}

	void setOnHeadersComplete(const infoCallback& fun)
	{
		static auto wrapper = fun;
		_settings.on_headers_complete = [](http_parser* parser){ return wrapper(HttpParser::Status(parser)); };
	}

	void setOnStatus(const dataCallback& fun)
	{
		static auto wrapper = fun;
		_settings.on_status = [](http_parser*, const char* buff, size_t len){ return wrapper(buff, len); };
	}

	void setOnBody(const dataCallback& fun)
	{
		static auto wrapper = fun;
		_settings.on_body = [](http_parser*, const char* buff, size_t len){ return wrapper(buff, len); };
	}

protected:
	std::unique_ptr<http_parser> _parser;
	http_parser_settings _settings;
};

HttpParser::HttpParser()
	: _pimpl(new Impl)
{
}

HttpParser::~HttpParser()
{
	delete _pimpl;
}

bool HttpParser::parseBuffer(const std::string& buffer)
{
	return _pimpl->parseBuffer(buffer.data(), buffer.size());
}

bool HttpParser::parseBuffer(const char* buffer, unsigned size)
{
	return _pimpl->parseBuffer(buffer, size);
}

void HttpParser::setOnMessageBegin(callback fun)
{
	_pimpl->setOnMessageBegin(fun);
}

void HttpParser::setOnMessageComplete(callback fun)
{
	_pimpl->setOnMessageComplete(fun);
}

void HttpParser::setOnUrl(dataCallback fun)
{
	_pimpl->setOnUrl(fun);
}

void HttpParser::setOnHeaderField(dataCallback fun)
{
	_pimpl->setOnHeaderField(fun);
}

void HttpParser::setOnHeaderValue(dataCallback fun)
{
	_pimpl->setOnHeaderValue(fun);
}

void HttpParser::setOnHeadersComplete(infoCallback fun)
{
	_pimpl->setOnHeadersComplete(fun);
}

void HttpParser::setOnStatus(dataCallback fun)
{
	_pimpl->setOnStatus(fun);
}

void HttpParser::setOnBody(dataCallback fun)
{
	_pimpl->setOnBody(fun);
}
<commit_msg>Ok... trying again w/ thread_local and doing the assignment *after* the static initialization (d'oh)<commit_after>#include "HttpParser.h"

#include "http_parser/http_parser.h"
#include <memory>

HttpParser::Status::Status(void* parser)
	: _parser(parser)
{
}

unsigned HttpParser::Status::method() const
{
	return static_cast<http_parser*>(_parser)->method;
}

unsigned HttpParser::Status::code() const
{
	return static_cast<http_parser*>(_parser)->status_code;
}

class HttpParser::Impl
{
public:
	Impl()
		: _parser(new http_parser)
		, _settings{0}
	{
		http_parser_init(_parser.get(), HTTP_REQUEST);
	}

	bool parseBuffer(const char* buffer, unsigned size)
	{
		int parsedSize = http_parser_execute(_parser.get(), &_settings, buffer, size);
		return parsedSize == size;
	}

//callbacks
public:
	void setOnMessageBegin(const callback& fun)
	{
		static thread_local callback wrapper;
		wrapper = fun;
		_settings.on_message_begin = [](http_parser*){ return wrapper(); };
	}

	void setOnMessageComplete(const callback& fun)
	{
		static thread_local callback wrapper;
		wrapper = fun;
		_settings.on_message_complete = [](http_parser*){ return wrapper(); };
	}

	void setOnUrl(const dataCallback& fun)
	{
		static thread_local dataCallback wrapper;
		wrapper = fun;
		_settings.on_url = [](http_parser*, const char* buff, size_t len){ return wrapper(buff, len); };
	}

	void setOnHeaderField(const dataCallback& fun)
	{
		static thread_local dataCallback wrapper;
		wrapper = fun;
		_settings.on_header_field = [](http_parser*, const char* buff, size_t len){ return wrapper(buff, len); };
	}

	void setOnHeaderValue(const dataCallback& fun)
	{
		static thread_local dataCallback wrapper;
		wrapper = fun;
		_settings.on_header_value = [](http_parser*, const char* buff, size_t len){ return wrapper(buff, len); };
	}

	void setOnHeadersComplete(const infoCallback& fun)
	{
		static thread_local infoCallback wrapper;
		wrapper = fun;
		_settings.on_headers_complete = [](http_parser* parser){ return wrapper(HttpParser::Status(parser)); };
	}

	void setOnStatus(const dataCallback& fun)
	{
		static thread_local dataCallback wrapper;
		wrapper = fun;
		_settings.on_status = [](http_parser*, const char* buff, size_t len){ return wrapper(buff, len); };
	}

	void setOnBody(const dataCallback& fun)
	{
		static thread_local dataCallback wrapper;
		wrapper = fun;
		_settings.on_body = [](http_parser*, const char* buff, size_t len){ return wrapper(buff, len); };
	}

protected:
	std::unique_ptr<http_parser> _parser;
	http_parser_settings _settings;
};

HttpParser::HttpParser()
	: _pimpl(new Impl)
{
}

HttpParser::~HttpParser()
{
	delete _pimpl;
}

bool HttpParser::parseBuffer(const std::string& buffer)
{
	return _pimpl->parseBuffer(buffer.data(), buffer.size());
}

bool HttpParser::parseBuffer(const char* buffer, unsigned size)
{
	return _pimpl->parseBuffer(buffer, size);
}

void HttpParser::setOnMessageBegin(callback fun)
{
	_pimpl->setOnMessageBegin(fun);
}

void HttpParser::setOnMessageComplete(callback fun)
{
	_pimpl->setOnMessageComplete(fun);
}

void HttpParser::setOnUrl(dataCallback fun)
{
	_pimpl->setOnUrl(fun);
}

void HttpParser::setOnHeaderField(dataCallback fun)
{
	_pimpl->setOnHeaderField(fun);
}

void HttpParser::setOnHeaderValue(dataCallback fun)
{
	_pimpl->setOnHeaderValue(fun);
}

void HttpParser::setOnHeadersComplete(infoCallback fun)
{
	_pimpl->setOnHeadersComplete(fun);
}

void HttpParser::setOnStatus(dataCallback fun)
{
	_pimpl->setOnStatus(fun);
}

void HttpParser::setOnBody(dataCallback fun)
{
	_pimpl->setOnBody(fun);
}
<|endoftext|>


<commit_before>///
/// @file   nth_prime3.cpp
/// @brief  Long distance nth prime testing.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesieve.hpp>

#include <stdint.h>
#include <iostream>
#include <cstdlib>

using namespace std;
using namespace primesieve;

void nth_prime_test(int64_t n, int64_t start, int64_t iters)
{
  for (int64_t i = 1; i <= iters; i++)
  {
    int64_t i_start = (i * start) + 1;
    int64_t prime = nth_prime(-n, i_start);
    int64_t smaller = nth_prime(n, prime - 1);
    int64_t larger = nth_prime(n, prime);

    if (smaller >= i_start || larger < i_start)
    {
      cerr << endl;
      cerr << "nth_prime(" << -n << ", " << i_start << ") = " << prime << "   ERROR" << endl;
      exit(1);
    }
  }
}

int main()
{
  for (int i = 3; i <= 7; i++)
  {
    for (int j = 10; j <= 13; j++)
    {
      int64_t n = (int64_t) pow(10.0, i);
      int64_t start = (int64_t) pow(10.0, j);
      int64_t iters = 5;

      cout << "nth_prime_test(" << n << ", " << start << ", " << iters << ")";
      nth_prime_test(n, start, iters);
      cout << " = OK" << endl;
    }
  }

  cout << endl;
  cout << "All tests passed successfully!" << endl;

  return 0;
}
<commit_msg>Refactor<commit_after>///
/// @file   nth_prime3.cpp
/// @brief  Long distance nth prime testing.
///
/// Copyright (C) 2017 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesieve.hpp>

#include <stdint.h>
#include <iostream>
#include <cstdlib>

using namespace std;
using namespace primesieve;

void nth_prime_test(int64_t n, int64_t start, int64_t iters)
{
  for (int64_t i = 1; i <= iters; i++)
  {
    int64_t i_start = (i * start) + 1;
    int64_t prime = nth_prime(-n, i_start);
    int64_t smaller = nth_prime(n, prime - 1);
    int64_t larger = nth_prime(n, prime);

    if (i_start <= smaller || i_start > larger)
    {
      cerr << endl;
      cerr << "nth_prime(" << -n << ", " << i_start << ") = " << prime << "   ERROR" << endl;
      exit(1);
    }
  }
}

int main()
{
  for (int i = 3; i <= 7; i++)
  {
    for (int j = 10; j <= 13; j++)
    {
      int64_t n = (int64_t) pow(10.0, i);
      int64_t start = (int64_t) pow(10.0, j);
      int64_t iters = 5;

      cout << "nth_prime_test(" << n << ", " << start << ", " << iters << ")";
      nth_prime_test(n, start, iters);
      cout << " = OK" << endl;
    }
  }

  cout << endl;
  cout << "All tests passed successfully!" << endl;

  return 0;
}
<|endoftext|>


<commit_before>/*
* OCSP subtypes
* (C) 2012 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/ocsp_types.h>
#include <botan/der_enc.h>
#include <botan/ber_dec.h>
#include <botan/x509_ext.h>
#include <botan/hash.h>
#include <botan/oids.h>

namespace Botan {

namespace OCSP {

CertID::CertID(const X509_Certificate& issuer,
               const BigInt& subject_serial)
   {
   /*
   In practice it seems some responders, including, notably,
   ocsp.verisign.com, will reject anything but SHA-1 here
   */
   std::unique_ptr<HashFunction> hash(HashFunction::create("SHA-160"));

   m_hash_id = AlgorithmIdentifier(hash->name(), AlgorithmIdentifier::USE_NULL_PARAM);
   m_issuer_key_hash = unlock(hash->process(issuer.subject_public_key_bitstring()));
   m_issuer_dn_hash = unlock(hash->process(issuer.raw_subject_dn()));
   m_subject_serial = subject_serial;
   }

bool CertID::is_id_for(const X509_Certificate& issuer,
                       const X509_Certificate& subject) const
   {
   try
      {
      if(BigInt::decode(subject.serial_number()) != m_subject_serial)
         return false;

      std::unique_ptr<HashFunction> hash(HashFunction::create(OIDS::lookup(m_hash_id.oid)));

      if(m_issuer_dn_hash != unlock(hash->process(subject.raw_issuer_dn())))
         return false;

      if(m_issuer_key_hash != unlock(hash->process(issuer.subject_public_key_bitstring())))
         return false;
      }
   catch(...)
      {
      return false;
      }

   return true;
   }

void CertID::encode_into(class DER_Encoder& to) const
   {
   to.start_cons(SEQUENCE)
      .encode(m_hash_id)
      .encode(m_issuer_dn_hash, OCTET_STRING)
      .encode(m_issuer_key_hash, OCTET_STRING)
      .encode(m_subject_serial)
      .end_cons();
   }

void CertID::decode_from(class BER_Decoder& from)
   {
   from.start_cons(SEQUENCE)
      .decode(m_hash_id)
      .decode(m_issuer_dn_hash, OCTET_STRING)
      .decode(m_issuer_key_hash, OCTET_STRING)
      .decode(m_subject_serial)
      .end_cons();

   }

void SingleResponse::encode_into(class DER_Encoder&) const
   {
   throw Not_Implemented("SingleResponse::encode_into");
   }

void SingleResponse::decode_from(class BER_Decoder& from)
   {
   BER_Object cert_status;
   Extensions extensions;

   from.start_cons(SEQUENCE)
      .decode(m_certid)
      .get_next(cert_status)
      .decode(m_thisupdate)
      .decode_optional(m_nextupdate, ASN1_Tag(0),
                       ASN1_Tag(CONTEXT_SPECIFIC | CONSTRUCTED))
      .decode_optional(extensions,
                       ASN1_Tag(1),
                       ASN1_Tag(CONTEXT_SPECIFIC | CONSTRUCTED))
      .end_cons();

   m_cert_status = cert_status.type_tag;
   }

}

}
<commit_msg>In OCSP::CertID don't crash if SHA-1 not available<commit_after>/*
* OCSP subtypes
* (C) 2012 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include <botan/ocsp_types.h>
#include <botan/der_enc.h>
#include <botan/ber_dec.h>
#include <botan/x509_ext.h>
#include <botan/hash.h>
#include <botan/oids.h>

namespace Botan {

namespace OCSP {

CertID::CertID(const X509_Certificate& issuer,
               const BigInt& subject_serial)
   {
   /*
   In practice it seems some responders, including, notably,
   ocsp.verisign.com, will reject anything but SHA-1 here
   */
   std::unique_ptr<HashFunction> hash(HashFunction::create_or_throw("SHA-160"));

   m_hash_id = AlgorithmIdentifier(hash->name(), AlgorithmIdentifier::USE_NULL_PARAM);
   m_issuer_key_hash = unlock(hash->process(issuer.subject_public_key_bitstring()));
   m_issuer_dn_hash = unlock(hash->process(issuer.raw_subject_dn()));
   m_subject_serial = subject_serial;
   }

bool CertID::is_id_for(const X509_Certificate& issuer,
                       const X509_Certificate& subject) const
   {
   try
      {
      if(BigInt::decode(subject.serial_number()) != m_subject_serial)
         return false;

      std::unique_ptr<HashFunction> hash(HashFunction::create(OIDS::lookup(m_hash_id.oid)));

      if(m_issuer_dn_hash != unlock(hash->process(subject.raw_issuer_dn())))
         return false;

      if(m_issuer_key_hash != unlock(hash->process(issuer.subject_public_key_bitstring())))
         return false;
      }
   catch(...)
      {
      return false;
      }

   return true;
   }

void CertID::encode_into(class DER_Encoder& to) const
   {
   to.start_cons(SEQUENCE)
      .encode(m_hash_id)
      .encode(m_issuer_dn_hash, OCTET_STRING)
      .encode(m_issuer_key_hash, OCTET_STRING)
      .encode(m_subject_serial)
      .end_cons();
   }

void CertID::decode_from(class BER_Decoder& from)
   {
   from.start_cons(SEQUENCE)
      .decode(m_hash_id)
      .decode(m_issuer_dn_hash, OCTET_STRING)
      .decode(m_issuer_key_hash, OCTET_STRING)
      .decode(m_subject_serial)
      .end_cons();

   }

void SingleResponse::encode_into(class DER_Encoder&) const
   {
   throw Not_Implemented("SingleResponse::encode_into");
   }

void SingleResponse::decode_from(class BER_Decoder& from)
   {
   BER_Object cert_status;
   Extensions extensions;

   from.start_cons(SEQUENCE)
      .decode(m_certid)
      .get_next(cert_status)
      .decode(m_thisupdate)
      .decode_optional(m_nextupdate, ASN1_Tag(0),
                       ASN1_Tag(CONTEXT_SPECIFIC | CONSTRUCTED))
      .decode_optional(extensions,
                       ASN1_Tag(1),
                       ASN1_Tag(CONTEXT_SPECIFIC | CONSTRUCTED))
      .end_cons();

   m_cert_status = cert_status.type_tag;
   }

}

}
<|endoftext|>


<commit_before>/*
 * Copyright 2009-2011 The VOTCA Development Team (http://www.votca.org)
 *
 * 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 <algorithm>
#include <votca/csg/topology.h>
#include <votca/csg/exclusionlist.h>

namespace votca { namespace csg {

void ExclusionList::Clear(void)
{
    list< exclusion_t *>::iterator iter;

    for(iter=_exclusions.begin();iter!=_exclusions.end();++iter)
        delete *iter;
    _exclusions.clear();
}

void ExclusionList::CreateExclusions(Topology *top) {
	InteractionContainer &ic = top->BondedInteractions();
	InteractionContainer::iterator ia;

	for (ia = ic.begin(); ia != ic.end(); ++ia) {
		int beads_in_int = (*ia)->BeadCount();
		list<Bead *> l;

		for (int ibead = 0; ibead < beads_in_int; ibead ++) {
			int ii = (*ia)->getBeadId(ibead);
			l.push_back(top->getBead(ii));
		}
		ExcludeList(l);
	}
}

bool ExclusionList::IsExcluded(Bead *bead1, Bead *bead2) {
    exclusion_t *excl;
    if(bead1->getMolecule() == bead2->getMolecule()) return false;
    if (bead2 < bead1) swap(bead1, bead2);
    if ((excl = GetExclusions(bead1))) {
        if(find(excl->_exclude.begin(), excl->_exclude.end(), bead2)
                != excl->_exclude.end()) return true;
    }
    return false;
}

std::ostream &operator<<(std::ostream &out, ExclusionList& exl)
{
    list<ExclusionList::exclusion_t*>::iterator ex;

    for(ex=exl._exclusions.begin();ex!=exl._exclusions.end();++ex) {
        list<Bead *>::iterator i;
        out << (int)((*ex)->_atom->getId()) + 1;
        for(i=(*ex)->_exclude.begin(); i!=(*ex)->_exclude.end(); ++i) {
            out << " " << ((*i)->getId()+1);
        }
        out << endl;
    }
    return out;
}

}}
<commit_msg>fixed Victor's new exclusion list scheme (fixes issue #165)<commit_after>/*
 * Copyright 2009-2011 The VOTCA Development Team (http://www.votca.org)
 *
 * 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 <algorithm>
#include <votca/csg/topology.h>
#include <votca/csg/exclusionlist.h>

namespace votca { namespace csg {

void ExclusionList::Clear(void)
{
    list< exclusion_t *>::iterator iter;

    for(iter=_exclusions.begin();iter!=_exclusions.end();++iter)
        delete *iter;
    _exclusions.clear();
}

void ExclusionList::CreateExclusions(Topology *top) {
	InteractionContainer &ic = top->BondedInteractions();
	InteractionContainer::iterator ia;

	for (ia = ic.begin(); ia != ic.end(); ++ia) {
		int beads_in_int = (*ia)->BeadCount();
		list<Bead *> l;

		for (int ibead = 0; ibead < beads_in_int; ibead ++) {
			int ii = (*ia)->getBeadId(ibead);
			l.push_back(top->getBead(ii));
		}
		ExcludeList(l);
	}
}

bool ExclusionList::IsExcluded(Bead *bead1, Bead *bead2) {
    exclusion_t *excl;
    if(bead1->getMolecule() != bead2->getMolecule()) return false;
    if (bead2 < bead1) swap(bead1, bead2);
    if ((excl = GetExclusions(bead1))) {
        if(find(excl->_exclude.begin(), excl->_exclude.end(), bead2)
                != excl->_exclude.end()) return true;
    }
    return false;
}

std::ostream &operator<<(std::ostream &out, ExclusionList& exl)
{
    list<ExclusionList::exclusion_t*>::iterator ex;

    for(ex=exl._exclusions.begin();ex!=exl._exclusions.end();++ex) {
        list<Bead *>::iterator i;
        out << (int)((*ex)->_atom->getId()) + 1;
        for(i=(*ex)->_exclude.begin(); i!=(*ex)->_exclude.end(); ++i) {
            out << " " << ((*i)->getId()+1);
        }
        out << endl;
    }
    return out;
}

}}
<|endoftext|>


<commit_before>#include <catch/catch.hpp>
#include <cmath>
#include <limits>
#include <RaPsCallion/serializer.h>

namespace rapscallion {
namespace test {

void test(const double in, const std::ptrdiff_t expected_size = -1) {
  Serializer s;
  serializer<decltype(+in)>::write(s, in);
  Deserializer d(s);

  const auto size = d.end - d.ptr;
  if (expected_size >= 0)
    CHECK(size == expected_size);

  // largest encoding of IEEE754 binary64 float:
  //  (11 exponent bits + exponent sign + NaN/inf flag) = 13 bits / 7 bit/byte = 2 byte
  //  (52 bit fraction + sign) = 53 bits / 7 bit/byte = 8 byte
  // + = 10 byte
  CHECK(size <= 10);

  const auto out = serializer<decltype(+in)>::read(d);
  if (std::isnan(in))
    CHECK(std::isnan(out));
  else
    CHECK(out == in);
}

}
}

TEST_CASE("Floats are serialized properly", "[serialization]") {
  using namespace rapscallion::test;

  // Smallest encodings, only requiring flags
  test(std::numeric_limits<double>::infinity(), 1);
  test(-std::numeric_limits<double>::infinity(), 1);
  test(std::numeric_limits<double>::quiet_NaN(), 1);
  test(0.0, 1);
  test(-0.0, 1);

  test(0.03125, 2);
  test(-0.03125, 2);
  test(0.0625, 2);
  test(-0.0625, 2);
  test(0.125, 2);
  test(-0.125, 2);
  test(0.25, 2);
  test(-0.25, 2);
  test(0.5, 2);
  test(-0.5, 2);
  test(1.0, 2);
  test(-1.0, 2);
  test(2.0, 2);
  test(-2.0, 2);
  test(M_PI, 9);
  test(-M_PI, 9);
  test((float)M_PI, 5);
  test(-(float)M_PI, 5);
  test(std::numeric_limits<double>::epsilon());
  test(std::numeric_limits<double>::min());
  test(std::numeric_limits<double>::max());
  test(std::numeric_limits<double>::denorm_min());
}
<commit_msg>Put test in BDD-style sections<commit_after>#include <catch/catch.hpp>
#include <cmath>
#include <limits>
#include <RaPsCallion/serializer.h>

namespace rapscallion {
namespace test {

void test(const std::string& inStr, const double in, const std::ptrdiff_t expected_size = -1) {
  GIVEN("the real number " + inStr) {
    WHEN("we serialize it") {
      Serializer s;
      serializer<decltype(+in)>::write(s, in);
      Deserializer d(s);

      THEN("the output meets size expectations") {
        const auto size = d.end - d.ptr;
        if (expected_size >= 0)
          CHECK(size == expected_size);

        // largest encoding of IEEE754 binary64 float:
        //  (11 exponent bits + exponent sign + NaN/inf flag) = 13 bits / 7 bit/byte = 2 byte
        //  (52 bit fraction + sign) = 53 bits / 7 bit/byte = 8 byte
        // + = 10 byte
        CHECK(size <= 10);

        AND_WHEN("we deserialize it again") {
          const auto out = serializer<decltype(+in)>::read(d);
          THEN("the deserialized output is equal to the original input") {
            if (std::isnan(in))
              CHECK(std::isnan(out));
            else
              CHECK(out == in);
          }
        }
      }
    }
  }
}

}
}

SCENARIO("Serializing floating point numbers", "[serialization]") {
  using namespace rapscallion::test;

#define STRIFY1ST(num, ...) #num
#define TEST(...) \
  test(STRIFY1ST(__VA_ARGS__, void), __VA_ARGS__)

  // Smallest encodings, only requiring flags
  TEST(std::numeric_limits<double>::infinity(), 1);
  TEST(-std::numeric_limits<double>::infinity(), 1);
  TEST(std::numeric_limits<double>::quiet_NaN(), 1);
  TEST(0.0, 1);
  TEST(-0.0, 1);

  TEST(0.03125, 2);
  TEST(-0.03125, 2);
  TEST(0.0625, 2);
  TEST(-0.0625, 2);
  TEST(0.125, 2);
  TEST(-0.125, 2);
  TEST(0.25, 2);
  TEST(-0.25, 2);
  TEST(0.5, 2);
  TEST(-0.5, 2);
  TEST(1.0, 2);
  TEST(-1.0, 2);
  TEST(2.0, 2);
  TEST(-2.0, 2);
  TEST(M_PI, 9);
  TEST(-M_PI, 9);
  TEST((float)M_PI, 5);
  TEST(-(float)M_PI, 5);
  TEST(std::numeric_limits<double>::epsilon());
  TEST(std::numeric_limits<double>::min());
  TEST(std::numeric_limits<double>::max(), 10);
  TEST(std::numeric_limits<double>::denorm_min());

#undef STRIFY
#undef TEST
}
<|endoftext|>


<commit_before>#ifdef _WIN32
	#include <windows.h>
	#include <boost/nowide/convert.hpp>
#else
	// any posix system
	#include <pthread.h>
#endif

#include <atomic>
#include <condition_variable>
#include <mutex>
#include <tbb/parallel_for.h>
#include <tbb/tbb_thread.h>
#include <tbb/task_scheduler_init.h>

#include "Thread.hpp"

namespace Slic3r {

#ifdef _WIN32
// The new API is better than the old SEH style thread naming since the names also show up in crash dumpsand ETW traces.
// Because the new API is only available on newer Windows 10, look it up dynamically.

typedef HRESULT(__stdcall* SetThreadDescriptionType)(HANDLE, PCWSTR);
typedef HRESULT(__stdcall* GetThreadDescriptionType)(HANDLE, PWSTR*);

static bool 					s_SetGetThreadDescriptionInitialized = false;
static HMODULE					s_hKernel32 = nullptr;
static SetThreadDescriptionType s_fnSetThreadDescription = nullptr;
static GetThreadDescriptionType	s_fnGetThreadDescription = nullptr;

static bool WindowsGetSetThreadNameAPIInitialize()
{
	if (! s_SetGetThreadDescriptionInitialized) {
		// Not thread safe! It is therefore a good idea to name the main thread before spawning worker threads
		// to initialize
		s_hKernel32 = LoadLibraryW(L"Kernel32.dll");
		if (s_hKernel32) {
			s_fnSetThreadDescription = (SetThreadDescriptionType)::GetProcAddress(s_hKernel32, "SetThreadDescription");
			s_fnGetThreadDescription = (GetThreadDescriptionType)::GetProcAddress(s_hKernel32, "GetThreadDescription");
		}
		s_SetGetThreadDescriptionInitialized = true;
	}
	return s_fnSetThreadDescription && s_fnGetThreadDescription;
}

#ifndef NDEBUG
	// Use the old way by throwing an exception, so at least in Debug mode the thread names are shown by the debugger.
	static constexpr DWORD MSVC_SEH_EXCEPTION_NAME_THREAD = 0x406D1388;

#pragma pack(push,8)
	typedef struct tagTHREADNAME_INFO
	{
		DWORD  dwType; 		// Must be 0x1000.
		LPCSTR szName; 		// Pointer to name (in user addr space).
		DWORD  dwThreadID; 	// Thread ID (-1=caller thread).
		DWORD  dwFlags; 	// Reserved for future use, must be zero.
	} THREADNAME_INFO;
#pragma pack(pop)

	static void WindowsSetThreadNameSEH(HANDLE hThread, const char* thread_name)
	{
		THREADNAME_INFO info;
		info.dwType 	= 0x1000;
		info.szName 	= thread_name;
		info.dwThreadID = ::GetThreadId(hThread);
		info.dwFlags 	= 0;
		__try {
			RaiseException(MSVC_SEH_EXCEPTION_NAME_THREAD, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
		} __except (EXCEPTION_EXECUTE_HANDLER) {
		}
	}
#endif // NDEBUG

static bool WindowsSetThreadName(HANDLE hThread, const char *thread_name)
{
	if (! WindowsGetSetThreadNameAPIInitialize()) {
#ifdef NDEBUG
		return false;
#else // NDEBUG
		// Running on Windows 7 or old Windows 7 in debug mode,
		// inform the debugger about the thread name by throwing an SEH.
		WindowsSetThreadNameSEH(hThread, thread_name);
		return true;
#endif // NDEBUG
	}

	size_t len = strlen(thread_name);
	if (len < 1024) {
		// Allocate the temp string on stack.
		wchar_t buf[1024];
		s_fnSetThreadDescription(hThread, boost::nowide::widen(buf, 1024, thread_name));
	} else {
		// Allocate dynamically.
		s_fnSetThreadDescription(hThread, boost::nowide::widen(thread_name).c_str());
	}
	return true;
}

bool set_thread_name(std::thread &thread, const char *thread_name)
{
   	return WindowsSetThreadName(static_cast<HANDLE>(thread.native_handle()), thread_name);
}

bool set_thread_name(boost::thread &thread, const char *thread_name)
{
   	return WindowsSetThreadName(static_cast<HANDLE>(thread.native_handle()), thread_name);
}

bool set_current_thread_name(const char *thread_name)
{
    return WindowsSetThreadName(::GetCurrentThread(), thread_name);
}

std::optional<std::string> get_current_thread_name()
{
	if (! WindowsGetSetThreadNameAPIInitialize())
		return std::nullopt;

	wchar_t *ptr = nullptr;
	s_fnGetThreadDescription(::GetCurrentThread(), &ptr);
	return (ptr == nullptr) ? std::string() : boost::nowide::narrow(ptr);
}

#else // _WIN32

#ifdef __APPLE__

// Appe screwed the Posix norm.
bool set_thread_name(std::thread &thread, const char *thread_name)
{
// not supported
//   	pthread_setname_np(thread.native_handle(), thread_name);
	return false;
}

bool set_thread_name(boost::thread &thread, const char *thread_name)
{
// not supported
//   	pthread_setname_np(thread.native_handle(), thread_name);
	return false;
}

bool set_current_thread_name(const char *thread_name)
{
	pthread_setname_np(thread_name);
	return true;
}

std::optional<std::string> get_current_thread_name()
{
// not supported
//	char buf[16];
//	return std::string(thread_getname_np(buf, 16) == 0 ? buf : "");
	return std::nullopt;
}

#else

// posix
bool set_thread_name(std::thread &thread, const char *thread_name)
{
   	pthread_setname_np(thread.native_handle(), thread_name);
	return true;
}

bool set_thread_name(boost::thread &thread, const char *thread_name)
{
   	pthread_setname_np(thread.native_handle(), thread_name);
	return true;
}

bool set_current_thread_name(const char *thread_name)
{
	pthread_setname_np(pthread_self(), thread_name);
	return true;
}

std::optional<std::string> get_current_thread_name()
{
	char buf[16];
	return std::string(pthread_getname_np(pthread_self(), buf, 16) == 0 ? buf : "");
}

#endif

#endif // _WIN32

// Spawn (n - 1) worker threads on Intel TBB thread pool and name them by an index and a system thread ID.
void name_tbb_thread_pool_threads()
{
	static bool initialized = false;
	if (initialized)
		return;
	initialized = true;

	const size_t nthreads_hw = std::thread::hardware_concurrency();
	size_t 		 nthreads    = nthreads_hw;

#ifdef SLIC3R_PROFILE
	// Shiny profiler is not thread safe, thus disable parallelization.
	nthreads = 1;
#endif

	if (nthreads != nthreads_hw)
		new tbb::task_scheduler_init(int(nthreads));

	std::atomic<size_t>		nthreads_running(0);
	std::condition_variable cv;
	std::mutex				cv_m;
	auto					master_thread_id = tbb::this_tbb_thread::get_id();
    tbb::parallel_for(
        tbb::blocked_range<size_t>(0, nthreads, 1),
        [&nthreads_running, nthreads, &master_thread_id, &cv, &cv_m](const tbb::blocked_range<size_t> &range) {
        	assert(range.begin() + 1 == range.end());
        	if (nthreads_running.fetch_add(1) + 1 == nthreads) {
        		// All threads are spinning.
        		// Wake them up.
    			cv.notify_all();
        	} else {
        		// Wait for the last thread to wake the others.
				std::unique_lock<std::mutex> lk(cv_m);
			    cv.wait(lk, [&nthreads_running, nthreads]{return nthreads_running == nthreads;});
        	}
        	auto thread_id = tbb::this_tbb_thread::get_id();
			if (thread_id == master_thread_id) {
				// The calling thread runs the 0'th task.
				assert(range.begin() == 0);
			} else {
				assert(range.begin() > 0);
				std::ostringstream name;
		        name << "slic3r_tbb_" << range.begin();
		        set_current_thread_name(name.str().c_str());
    		}
        });
}

}
<commit_msg>Fix of PrusaSlicer hangs on Linux when run with non standard task affinity #5661<commit_after>#ifdef _WIN32
	#include <windows.h>
	#include <boost/nowide/convert.hpp>
#else
	// any posix system
	#include <pthread.h>
#endif

#include <atomic>
#include <condition_variable>
#include <mutex>
#include <tbb/parallel_for.h>
#include <tbb/tbb_thread.h>
#include <tbb/task_arena.h>
#include <tbb/task_scheduler_init.h>

#include "Thread.hpp"

namespace Slic3r {

#ifdef _WIN32
// The new API is better than the old SEH style thread naming since the names also show up in crash dumpsand ETW traces.
// Because the new API is only available on newer Windows 10, look it up dynamically.

typedef HRESULT(__stdcall* SetThreadDescriptionType)(HANDLE, PCWSTR);
typedef HRESULT(__stdcall* GetThreadDescriptionType)(HANDLE, PWSTR*);

static bool 					s_SetGetThreadDescriptionInitialized = false;
static HMODULE					s_hKernel32 = nullptr;
static SetThreadDescriptionType s_fnSetThreadDescription = nullptr;
static GetThreadDescriptionType	s_fnGetThreadDescription = nullptr;

static bool WindowsGetSetThreadNameAPIInitialize()
{
	if (! s_SetGetThreadDescriptionInitialized) {
		// Not thread safe! It is therefore a good idea to name the main thread before spawning worker threads
		// to initialize
		s_hKernel32 = LoadLibraryW(L"Kernel32.dll");
		if (s_hKernel32) {
			s_fnSetThreadDescription = (SetThreadDescriptionType)::GetProcAddress(s_hKernel32, "SetThreadDescription");
			s_fnGetThreadDescription = (GetThreadDescriptionType)::GetProcAddress(s_hKernel32, "GetThreadDescription");
		}
		s_SetGetThreadDescriptionInitialized = true;
	}
	return s_fnSetThreadDescription && s_fnGetThreadDescription;
}

#ifndef NDEBUG
	// Use the old way by throwing an exception, so at least in Debug mode the thread names are shown by the debugger.
	static constexpr DWORD MSVC_SEH_EXCEPTION_NAME_THREAD = 0x406D1388;

#pragma pack(push,8)
	typedef struct tagTHREADNAME_INFO
	{
		DWORD  dwType; 		// Must be 0x1000.
		LPCSTR szName; 		// Pointer to name (in user addr space).
		DWORD  dwThreadID; 	// Thread ID (-1=caller thread).
		DWORD  dwFlags; 	// Reserved for future use, must be zero.
	} THREADNAME_INFO;
#pragma pack(pop)

	static void WindowsSetThreadNameSEH(HANDLE hThread, const char* thread_name)
	{
		THREADNAME_INFO info;
		info.dwType 	= 0x1000;
		info.szName 	= thread_name;
		info.dwThreadID = ::GetThreadId(hThread);
		info.dwFlags 	= 0;
		__try {
			RaiseException(MSVC_SEH_EXCEPTION_NAME_THREAD, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
		} __except (EXCEPTION_EXECUTE_HANDLER) {
		}
	}
#endif // NDEBUG

static bool WindowsSetThreadName(HANDLE hThread, const char *thread_name)
{
	if (! WindowsGetSetThreadNameAPIInitialize()) {
#ifdef NDEBUG
		return false;
#else // NDEBUG
		// Running on Windows 7 or old Windows 7 in debug mode,
		// inform the debugger about the thread name by throwing an SEH.
		WindowsSetThreadNameSEH(hThread, thread_name);
		return true;
#endif // NDEBUG
	}

	size_t len = strlen(thread_name);
	if (len < 1024) {
		// Allocate the temp string on stack.
		wchar_t buf[1024];
		s_fnSetThreadDescription(hThread, boost::nowide::widen(buf, 1024, thread_name));
	} else {
		// Allocate dynamically.
		s_fnSetThreadDescription(hThread, boost::nowide::widen(thread_name).c_str());
	}
	return true;
}

bool set_thread_name(std::thread &thread, const char *thread_name)
{
   	return WindowsSetThreadName(static_cast<HANDLE>(thread.native_handle()), thread_name);
}

bool set_thread_name(boost::thread &thread, const char *thread_name)
{
   	return WindowsSetThreadName(static_cast<HANDLE>(thread.native_handle()), thread_name);
}

bool set_current_thread_name(const char *thread_name)
{
    return WindowsSetThreadName(::GetCurrentThread(), thread_name);
}

std::optional<std::string> get_current_thread_name()
{
	if (! WindowsGetSetThreadNameAPIInitialize())
		return std::nullopt;

	wchar_t *ptr = nullptr;
	s_fnGetThreadDescription(::GetCurrentThread(), &ptr);
	return (ptr == nullptr) ? std::string() : boost::nowide::narrow(ptr);
}

#else // _WIN32

#ifdef __APPLE__

// Appe screwed the Posix norm.
bool set_thread_name(std::thread &thread, const char *thread_name)
{
// not supported
//   	pthread_setname_np(thread.native_handle(), thread_name);
	return false;
}

bool set_thread_name(boost::thread &thread, const char *thread_name)
{
// not supported
//   	pthread_setname_np(thread.native_handle(), thread_name);
	return false;
}

bool set_current_thread_name(const char *thread_name)
{
	pthread_setname_np(thread_name);
	return true;
}

std::optional<std::string> get_current_thread_name()
{
// not supported
//	char buf[16];
//	return std::string(thread_getname_np(buf, 16) == 0 ? buf : "");
	return std::nullopt;
}

#else

// posix
bool set_thread_name(std::thread &thread, const char *thread_name)
{
   	pthread_setname_np(thread.native_handle(), thread_name);
	return true;
}

bool set_thread_name(boost::thread &thread, const char *thread_name)
{
   	pthread_setname_np(thread.native_handle(), thread_name);
	return true;
}

bool set_current_thread_name(const char *thread_name)
{
	pthread_setname_np(pthread_self(), thread_name);
	return true;
}

std::optional<std::string> get_current_thread_name()
{
	char buf[16];
	return std::string(pthread_getname_np(pthread_self(), buf, 16) == 0 ? buf : "");
}

#endif

#endif // _WIN32

// Spawn (n - 1) worker threads on Intel TBB thread pool and name them by an index and a system thread ID.
void name_tbb_thread_pool_threads()
{
	static bool initialized = false;
	if (initialized)
		return;
	initialized = true;

	// see GH issue #5661 PrusaSlicer hangs on Linux when run with non standard task affinity
	// TBB will respect the task affinity mask on Linux and spawn less threads than std::thread::hardware_concurrency().
//	const size_t nthreads_hw = std::thread::hardware_concurrency();
	const size_t nthreads_hw = tbb::this_task_arena::max_concurrency();
	size_t 		 nthreads    = nthreads_hw;

#ifdef SLIC3R_PROFILE
	// Shiny profiler is not thread safe, thus disable parallelization.
	nthreads = 1;
#endif

	if (nthreads != nthreads_hw)
		new tbb::task_scheduler_init(int(nthreads));

	std::atomic<size_t>		nthreads_running(0);
	std::condition_variable cv;
	std::mutex				cv_m;
	auto					master_thread_id = tbb::this_tbb_thread::get_id();
    tbb::parallel_for(
        tbb::blocked_range<size_t>(0, nthreads, 1),
        [&nthreads_running, nthreads, &master_thread_id, &cv, &cv_m](const tbb::blocked_range<size_t> &range) {
        	assert(range.begin() + 1 == range.end());
        	if (nthreads_running.fetch_add(1) + 1 == nthreads) {
        		// All threads are spinning.
        		// Wake them up.
    			cv.notify_all();
        	} else {
        		// Wait for the last thread to wake the others.
				std::unique_lock<std::mutex> lk(cv_m);
			    cv.wait(lk, [&nthreads_running, nthreads]{return nthreads_running == nthreads;});
        	}
        	auto thread_id = tbb::this_tbb_thread::get_id();
			if (thread_id == master_thread_id) {
				// The calling thread runs the 0'th task.
				assert(range.begin() == 0);
			} else {
				assert(range.begin() > 0);
				std::ostringstream name;
		        name << "slic3r_tbb_" << range.begin();
		        set_current_thread_name(name.str().c_str());
    		}
        });
}

}
<|endoftext|>