<commit_before>//===------------------------- chrono.cpp ---------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "chrono"
#include "cerrno"        // errno
#include "system_error"  // __throw_system_error
#include <time.h>        // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME
#include "include/apple_availability.h"

#if !defined(__APPLE__)
#define _LIBCPP_USE_CLOCK_GETTIME
#endif // __APPLE__

#if defined(_LIBCPP_WIN32API)
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRA_LEAN
#include <windows.h>
#if _WIN32_WINNT >= _WIN32_WINNT_WIN8
#include <winapifamily.h>
#endif
#else
#if !defined(CLOCK_REALTIME) || !defined(_LIBCPP_USE_CLOCK_GETTIME)
#include <sys/time.h>        // for gettimeofday and timeval
#endif // !defined(CLOCK_REALTIME)
#endif // defined(_LIBCPP_WIN32API)

#if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK)
#if __APPLE__
#include <mach/mach_time.h>  // mach_absolute_time, mach_timebase_info_data_t
#elif !defined(_LIBCPP_WIN32API) && !defined(CLOCK_MONOTONIC)
#error "Monotonic clock not implemented"
#endif
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

namespace chrono
{

// system_clock

const bool system_clock::is_steady;

system_clock::time_point
system_clock::now() _NOEXCEPT
{
#if defined(_LIBCPP_WIN32API)
  // FILETIME is in 100ns units
  using filetime_duration =
      _VSTD::chrono::duration<__int64,
                              _VSTD::ratio_multiply<_VSTD::ratio<100, 1>,
                                                    nanoseconds::period>>;

  // The Windows epoch is Jan 1 1601, the Unix epoch Jan 1 1970.
  static _LIBCPP_CONSTEXPR const seconds nt_to_unix_epoch{11644473600};

  FILETIME ft;
#if _WIN32_WINNT >= _WIN32_WINNT_WIN8
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  GetSystemTimePreciseAsFileTime(&ft);
#else
  GetSystemTimeAsFileTime(&ft);
#endif
#else
  GetSystemTimeAsFileTime(&ft);
#endif

  filetime_duration d{(static_cast<__int64>(ft.dwHighDateTime) << 32) |
                       static_cast<__int64>(ft.dwLowDateTime)};
  return time_point(duration_cast<duration>(d - nt_to_unix_epoch));
#else
#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
  struct timespec tp;
  if (0 != clock_gettime(CLOCK_REALTIME, &tp))
    __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed");
  return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000));
#else
    timeval tv;
    gettimeofday(&tv, 0);
    return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
#endif // _LIBCPP_USE_CLOCK_GETTIME && CLOCK_REALTIME
#endif
}

time_t
system_clock::to_time_t(const time_point& t) _NOEXCEPT
{
    return time_t(duration_cast<seconds>(t.time_since_epoch()).count());
}

system_clock::time_point
system_clock::from_time_t(time_t t) _NOEXCEPT
{
    return system_clock::time_point(seconds(t));
}

#ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK
// steady_clock
//
// Warning:  If this is not truly steady, then it is non-conforming.  It is
//  better for it to not exist and have the rest of libc++ use system_clock
//  instead.

const bool steady_clock::is_steady;

#if defined(__APPLE__)

// Darwin libc versions >= 1133 provide ns precision via CLOCK_UPTIME_RAW
#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW)
steady_clock::time_point
steady_clock::now() _NOEXCEPT
{
    struct timespec tp;
    if (0 != clock_gettime(CLOCK_UPTIME_RAW, &tp))
        __throw_system_error(errno, "clock_gettime(CLOCK_UPTIME_RAW) failed");
    return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
}

#else
//   mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of
//   nanoseconds since the computer booted up.  MachInfo.numer and MachInfo.denom
//   are run time constants supplied by the OS.  This clock has no relationship
//   to the Gregorian calendar.  It's main use is as a high resolution timer.

// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment.  Specialize
//   for that case as an optimization.

static
steady_clock::rep
steady_simplified()
{
    return static_cast<steady_clock::rep>(mach_absolute_time());
}

static
double
compute_steady_factor()
{
    mach_timebase_info_data_t MachInfo;
    mach_timebase_info(&MachInfo);
    return static_cast<double>(MachInfo.numer) / MachInfo.denom;
}

static
steady_clock::rep
steady_full()
{
    static const double factor = compute_steady_factor();
    return static_cast<steady_clock::rep>(mach_absolute_time() * factor);
}

typedef steady_clock::rep (*FP)();

static
FP
init_steady_clock()
{
    mach_timebase_info_data_t MachInfo;
    mach_timebase_info(&MachInfo);
    if (MachInfo.numer == MachInfo.denom)
        return &steady_simplified;
    return &steady_full;
}

steady_clock::time_point
steady_clock::now() _NOEXCEPT
{
    static FP fp = init_steady_clock();
    return time_point(duration(fp()));
}
#endif // defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW)

#elif defined(_LIBCPP_WIN32API)

steady_clock::time_point
steady_clock::now() _NOEXCEPT
{
  static LARGE_INTEGER freq;
  static BOOL initialized = FALSE;
  if (!initialized)
    initialized = QueryPerformanceFrequency(&freq); // always succceeds

  LARGE_INTEGER counter;
  QueryPerformanceCounter(&counter);
  return time_point(duration(counter.QuadPart * nano::den / freq.QuadPart));
}

#elif defined(CLOCK_MONOTONIC)

// On Apple platforms only CLOCK_UPTIME_RAW or mach_absolute_time are able to
// time functions in the nanosecond range. Thus, they are the only acceptable
// implementations of steady_clock.
#ifdef __APPLE__
#error "Never use CLOCK_MONOTONIC for steady_clock::now on Apple platforms"
#endif

steady_clock::time_point
steady_clock::now() _NOEXCEPT
{
    struct timespec tp;
    if (0 != clock_gettime(CLOCK_MONOTONIC, &tp))
        __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed");
    return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
}

#else
#error "Monotonic clock not implemented"
#endif

#endif // !_LIBCPP_HAS_NO_MONOTONIC_CLOCK

}

_LIBCPP_END_NAMESPACE_STD
<commit_msg>Fix PR#41323 'Race condition in steady_clock::now for _LIBCPP_WIN32API'. thanks to Ivan Afanasyev for the report.<commit_after>//===------------------------- chrono.cpp ---------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "chrono"
#include "cerrno"        // errno
#include "system_error"  // __throw_system_error
#include <time.h>        // clock_gettime, CLOCK_MONOTONIC and CLOCK_REALTIME
#include "include/apple_availability.h"

#if !defined(__APPLE__)
#define _LIBCPP_USE_CLOCK_GETTIME
#endif // __APPLE__

#if defined(_LIBCPP_WIN32API)
#define WIN32_LEAN_AND_MEAN
#define VC_EXTRA_LEAN
#include <windows.h>
#if _WIN32_WINNT >= _WIN32_WINNT_WIN8
#include <winapifamily.h>
#endif
#else
#if !defined(CLOCK_REALTIME) || !defined(_LIBCPP_USE_CLOCK_GETTIME)
#include <sys/time.h>        // for gettimeofday and timeval
#endif // !defined(CLOCK_REALTIME)
#endif // defined(_LIBCPP_WIN32API)

#if !defined(_LIBCPP_HAS_NO_MONOTONIC_CLOCK)
#if __APPLE__
#include <mach/mach_time.h>  // mach_absolute_time, mach_timebase_info_data_t
#elif !defined(_LIBCPP_WIN32API) && !defined(CLOCK_MONOTONIC)
#error "Monotonic clock not implemented"
#endif
#endif

_LIBCPP_BEGIN_NAMESPACE_STD

namespace chrono
{

// system_clock

const bool system_clock::is_steady;

system_clock::time_point
system_clock::now() _NOEXCEPT
{
#if defined(_LIBCPP_WIN32API)
  // FILETIME is in 100ns units
  using filetime_duration =
      _VSTD::chrono::duration<__int64,
                              _VSTD::ratio_multiply<_VSTD::ratio<100, 1>,
                                                    nanoseconds::period>>;

  // The Windows epoch is Jan 1 1601, the Unix epoch Jan 1 1970.
  static _LIBCPP_CONSTEXPR const seconds nt_to_unix_epoch{11644473600};

  FILETIME ft;
#if _WIN32_WINNT >= _WIN32_WINNT_WIN8
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
  GetSystemTimePreciseAsFileTime(&ft);
#else
  GetSystemTimeAsFileTime(&ft);
#endif
#else
  GetSystemTimeAsFileTime(&ft);
#endif

  filetime_duration d{(static_cast<__int64>(ft.dwHighDateTime) << 32) |
                       static_cast<__int64>(ft.dwLowDateTime)};
  return time_point(duration_cast<duration>(d - nt_to_unix_epoch));
#else
#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_REALTIME)
  struct timespec tp;
  if (0 != clock_gettime(CLOCK_REALTIME, &tp))
    __throw_system_error(errno, "clock_gettime(CLOCK_REALTIME) failed");
  return time_point(seconds(tp.tv_sec) + microseconds(tp.tv_nsec / 1000));
#else
    timeval tv;
    gettimeofday(&tv, 0);
    return time_point(seconds(tv.tv_sec) + microseconds(tv.tv_usec));
#endif // _LIBCPP_USE_CLOCK_GETTIME && CLOCK_REALTIME
#endif
}

time_t
system_clock::to_time_t(const time_point& t) _NOEXCEPT
{
    return time_t(duration_cast<seconds>(t.time_since_epoch()).count());
}

system_clock::time_point
system_clock::from_time_t(time_t t) _NOEXCEPT
{
    return system_clock::time_point(seconds(t));
}

#ifndef _LIBCPP_HAS_NO_MONOTONIC_CLOCK
// steady_clock
//
// Warning:  If this is not truly steady, then it is non-conforming.  It is
//  better for it to not exist and have the rest of libc++ use system_clock
//  instead.

const bool steady_clock::is_steady;

#if defined(__APPLE__)

// Darwin libc versions >= 1133 provide ns precision via CLOCK_UPTIME_RAW
#if defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW)
steady_clock::time_point
steady_clock::now() _NOEXCEPT
{
    struct timespec tp;
    if (0 != clock_gettime(CLOCK_UPTIME_RAW, &tp))
        __throw_system_error(errno, "clock_gettime(CLOCK_UPTIME_RAW) failed");
    return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
}

#else
//   mach_absolute_time() * MachInfo.numer / MachInfo.denom is the number of
//   nanoseconds since the computer booted up.  MachInfo.numer and MachInfo.denom
//   are run time constants supplied by the OS.  This clock has no relationship
//   to the Gregorian calendar.  It's main use is as a high resolution timer.

// MachInfo.numer / MachInfo.denom is often 1 on the latest equipment.  Specialize
//   for that case as an optimization.

static
steady_clock::rep
steady_simplified()
{
    return static_cast<steady_clock::rep>(mach_absolute_time());
}

static
double
compute_steady_factor()
{
    mach_timebase_info_data_t MachInfo;
    mach_timebase_info(&MachInfo);
    return static_cast<double>(MachInfo.numer) / MachInfo.denom;
}

static
steady_clock::rep
steady_full()
{
    static const double factor = compute_steady_factor();
    return static_cast<steady_clock::rep>(mach_absolute_time() * factor);
}

typedef steady_clock::rep (*FP)();

static
FP
init_steady_clock()
{
    mach_timebase_info_data_t MachInfo;
    mach_timebase_info(&MachInfo);
    if (MachInfo.numer == MachInfo.denom)
        return &steady_simplified;
    return &steady_full;
}

steady_clock::time_point
steady_clock::now() _NOEXCEPT
{
    static FP fp = init_steady_clock();
    return time_point(duration(fp()));
}
#endif // defined(_LIBCPP_USE_CLOCK_GETTIME) && defined(CLOCK_UPTIME_RAW)

#elif defined(_LIBCPP_WIN32API)

// https://msdn.microsoft.com/en-us/library/windows/desktop/ms644905(v=vs.85).aspx says:
//    If the function fails, the return value is zero. <snip>
//    On systems that run Windows XP or later, the function will always succeed
//      and will thus never return zero.

static LARGE_INTEGER
__QueryPerformanceFrequency()
{
	LARGE_INTEGER val;
	(void) QueryPerformanceFrequency(&val);
	return val;
}

steady_clock::time_point
steady_clock::now() _NOEXCEPT
{
  static const LARGE_INTEGER freq = __QueryPerformanceFrequency();

  LARGE_INTEGER counter = __QueryPerformanceFrequency();
  return time_point(duration(counter.QuadPart * nano::den / freq.QuadPart));
}

#elif defined(CLOCK_MONOTONIC)

// On Apple platforms only CLOCK_UPTIME_RAW or mach_absolute_time are able to
// time functions in the nanosecond range. Thus, they are the only acceptable
// implementations of steady_clock.
#ifdef __APPLE__
#error "Never use CLOCK_MONOTONIC for steady_clock::now on Apple platforms"
#endif

steady_clock::time_point
steady_clock::now() _NOEXCEPT
{
    struct timespec tp;
    if (0 != clock_gettime(CLOCK_MONOTONIC, &tp))
        __throw_system_error(errno, "clock_gettime(CLOCK_MONOTONIC) failed");
    return time_point(seconds(tp.tv_sec) + nanoseconds(tp.tv_nsec));
}

#else
#error "Monotonic clock not implemented"
#endif

#endif // !_LIBCPP_HAS_NO_MONOTONIC_CLOCK

}

_LIBCPP_END_NAMESPACE_STD
<|endoftext|>


<commit_before>/*
    Copyright (c) 2008 Volker Krause <vkrause@kde.org>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 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 Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "configdialog.h"
#include "settings.h"

#include <kconfigdialogmanager.h>
#include <kdebug.h>
#include <kmessagebox.h>
#include <KUser>

#include <QWhatsThis>

ConfigDialog::ConfigDialog( QWidget * parent ) :
        KDialog( parent )
{
    m_comm = new Communication( this );
    connect( m_comm, SIGNAL( authOk() ), SLOT( slotAuthOk() ) );
    connect( m_comm, SIGNAL( authFailed( const QString& ) ), SLOT( slotAuthFailed( const QString& ) ) );
    ui.setupUi( mainWidget() );
    mManager = new KConfigDialogManager( this, Settings::self() );
    mManager->updateWidgets();
    ui.password->setText( Settings::self()->password() );
    if (ui.kcfg_Name->text().isEmpty() ) {
        KUser user;
        QString usersName = user.property( KUser::FullName ).toString();
        if ( usersName.isEmpty() )
            usersName = user.loginName();
        if ( !usersName.isEmpty() )
            ui.kcfg_Name->setText( usersName );
    }
    setButtons( KDialog::Ok | KDialog::Cancel );
    ui.testButton->setEnabled(!ui.kcfg_Name->text().isEmpty());
    connect( ui.testButton, SIGNAL( clicked() ), SLOT( slotTestClicked() ) );
    connect( ui.kcfg_UserName, SIGNAL(textChanged(const QString&)), SLOT(slotTextChanged(const QString&)));
    connect( ui.openidLabel, SIGNAL( linkActivated ( const QString & ) ), SLOT( slotLinkClicked() ) );
}

ConfigDialog::~ConfigDialog()
{
    delete m_comm;
}

void ConfigDialog::slotTestClicked()
{
    kDebug() << "Test request" << ui.kcfg_Service->currentIndex()
    << ui.kcfg_UserName->text() << ui.password->text();
    setCursor( Qt::BusyCursor );
    ui.statusLabel->setText( i18n( "Checking..." ) );
    ui.testButton->setEnabled( false );
    m_comm->setService( ui.kcfg_Service->currentIndex() );
    m_comm->setCredentials( ui.kcfg_UserName->text(), ui.password->text() );
    m_comm->checkAuth();
}

void ConfigDialog::slotTextChanged(const QString &text)
{
    ui.testButton->setEnabled(!text.isEmpty());
}

void ConfigDialog::slotButtonClicked( int button )
{
    if (button == KDialog::Ok) {
        Settings::self()->setPassword( ui.password->text() );
        mManager->updateSettings();
        accept();
    }  else {
        KDialog::slotButtonClicked(button);
    }
 }

void ConfigDialog::slotAuthOk()
{
    unsetCursor();
    ui.testButton->setEnabled( true );
    ui.statusLabel->setText( i18n( "OK" ) );
    ui.statusImageLabel->setPixmap( KIcon( "dialog-ok" ).pixmap( 16 ) );
    Settings::self()->setPassword( ui.password->text() );
    mManager->updateSettings();
}

void ConfigDialog::slotAuthFailed( const QString& error )
{
    unsetCursor();
    ui.statusLabel->setText( i18n( "Failed" ) );
    ui.statusImageLabel->setPixmap( KIcon( "dialog-cancel" ).pixmap( 16 ) );
    ui.testButton->setEnabled( true );
}

void ConfigDialog::slotLinkClicked()
{
    QWhatsThis::showText( QCursor::pos(), i18n( "OpenId users must first specify a password in "
        "the settings on the webpage. However, OpenId cannot be used." ), this );
}

#include "configdialog.moc"
<commit_msg>String now makes some sort of sense.<commit_after>/*
    Copyright (c) 2008 Volker Krause <vkrause@kde.org>

    This library is free software; you can redistribute it and/or modify it
    under the terms of the GNU Library General Public License as published by
    the Free Software Foundation; either version 2 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 Library General Public
    License for more details.

    You should have received a copy of the GNU Library General Public License
    along with this library; see the file COPYING.LIB.  If not, write to the
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
*/

#include "configdialog.h"
#include "settings.h"

#include <kconfigdialogmanager.h>
#include <kdebug.h>
#include <kmessagebox.h>
#include <KUser>

#include <QWhatsThis>

ConfigDialog::ConfigDialog( QWidget * parent ) :
        KDialog( parent )
{
    m_comm = new Communication( this );
    connect( m_comm, SIGNAL( authOk() ), SLOT( slotAuthOk() ) );
    connect( m_comm, SIGNAL( authFailed( const QString& ) ), SLOT( slotAuthFailed( const QString& ) ) );
    ui.setupUi( mainWidget() );
    mManager = new KConfigDialogManager( this, Settings::self() );
    mManager->updateWidgets();
    ui.password->setText( Settings::self()->password() );
    if (ui.kcfg_Name->text().isEmpty() ) {
        KUser user;
        QString usersName = user.property( KUser::FullName ).toString();
        if ( usersName.isEmpty() )
            usersName = user.loginName();
        if ( !usersName.isEmpty() )
            ui.kcfg_Name->setText( usersName );
    }
    setButtons( KDialog::Ok | KDialog::Cancel );
    ui.testButton->setEnabled(!ui.kcfg_Name->text().isEmpty());
    connect( ui.testButton, SIGNAL( clicked() ), SLOT( slotTestClicked() ) );
    connect( ui.kcfg_UserName, SIGNAL(textChanged(const QString&)), SLOT(slotTextChanged(const QString&)));
    connect( ui.openidLabel, SIGNAL( linkActivated ( const QString & ) ), SLOT( slotLinkClicked() ) );
}

ConfigDialog::~ConfigDialog()
{
    delete m_comm;
}

void ConfigDialog::slotTestClicked()
{
    kDebug() << "Test request" << ui.kcfg_Service->currentIndex()
    << ui.kcfg_UserName->text() << ui.password->text();
    setCursor( Qt::BusyCursor );
    ui.statusLabel->setText( i18n( "Checking..." ) );
    ui.testButton->setEnabled( false );
    m_comm->setService( ui.kcfg_Service->currentIndex() );
    m_comm->setCredentials( ui.kcfg_UserName->text(), ui.password->text() );
    m_comm->checkAuth();
}

void ConfigDialog::slotTextChanged(const QString &text)
{
    ui.testButton->setEnabled(!text.isEmpty());
}

void ConfigDialog::slotButtonClicked( int button )
{
    if (button == KDialog::Ok) {
        Settings::self()->setPassword( ui.password->text() );
        mManager->updateSettings();
        accept();
    }  else {
        KDialog::slotButtonClicked(button);
    }
 }

void ConfigDialog::slotAuthOk()
{
    unsetCursor();
    ui.testButton->setEnabled( true );
    ui.statusLabel->setText( i18n( "OK" ) );
    ui.statusImageLabel->setPixmap( KIcon( "dialog-ok" ).pixmap( 16 ) );
    Settings::self()->setPassword( ui.password->text() );
    mManager->updateSettings();
}

void ConfigDialog::slotAuthFailed( const QString& error )
{
    unsetCursor();
    ui.statusLabel->setText( i18n( "Failed" ) );
    ui.statusImageLabel->setPixmap( KIcon( "dialog-cancel" ).pixmap( 16 ) );
    ui.testButton->setEnabled( true );
}

void ConfigDialog::slotLinkClicked()
{
    QWhatsThis::showText( QCursor::pos(), i18n( "OpenId users must first specify a password in "
        "the settings on the webpage, as this resource cannot use OpenId." ), this );
}

#include "configdialog.moc"
<|endoftext|>


<commit_before>#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <fcntl.h>
// sudo apt-get install libfreeimageplus-dev
#include <FreeImagePlus.h>
#include <sys/mman.h>
#include <stdint.h>

void usage(char *argv[])
{
    fprintf(stderr, "\n");
    fprintf(stderr, "Usage: %s imagename fbaddress bytes_per_row [mode]\n", argv[0]);
    fprintf(stderr, "\t\"mode\" can be 8 for 8-byte pixels or 4 for 4 bytes or 3 for 3 bytes.\n");
    fprintf(stderr, "\tThe default for \"mode\" is 8.\n");
    fprintf(stderr, "\n");
    exit(EXIT_FAILURE);
}

static const unsigned int FRAMEBUFFER_WIDTH = 800;
static const unsigned int FRAMEBUFFER_HEIGHT = 480;

int main(int argc, char **argv)
{
    if(argc < 4 || argc > 5) {
        usage(argv);
    }

    unsigned int address = strtoul(argv[2], NULL, 0);
    unsigned int bytes_per_row = strtoul(argv[3], NULL, 0);

    int bytes_per_pixel;
    int mode = 8;

    if(argc > 4) {
        mode = atoi(argv[4]);
    }

    switch(mode) {
        case 3: bytes_per_pixel = 3; break;
        case 4: bytes_per_pixel = 4; break;
        case 8: bytes_per_pixel = 8; break;

        default:
            std::cerr << "unsupported mode " << mode << std::endl;
            exit(EXIT_FAILURE);
            break;
    }

    printf("Address = 0x%08X\n", address);
    printf("Bytes per row = %d\n", bytes_per_row);
    printf("Mode = %d (bytes per pixel = %d)\n", mode, bytes_per_pixel);
    FreeImage_Initialise();

    const char *filename = argv[1];

    fipImage img;
    if (!img.load(filename)) {
        std::cerr << "failed to load image " << filename << std::endl;
        exit(EXIT_FAILURE);
    }

    if (!img.convertTo32Bits()) {
	std::cerr << "Couldn't convert image to 32 bits " << filename << std::endl;
	exit(EXIT_FAILURE);
    }

    if(img.getImageType() == FIT_RGBF) {
        std::cerr << "image is incompatible type RGBF" << std::endl;
        exit(EXIT_FAILURE);
    }

    if(img.getImageType() != FIT_BITMAP) {
        std::cerr << "image is incompatible type " << img.getImageType() << std::endl;
        exit(EXIT_FAILURE);
    }

    int dev_mem = open("/dev/mem", O_RDWR);

    if(dev_mem == 0) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    unsigned char *fb = (unsigned char *)mmap(0, FRAMEBUFFER_HEIGHT * bytes_per_row, PROT_READ | PROT_WRITE, /* MAP_NOCACHE | */ MAP_SHARED , dev_mem, address);

    if(fb == 0) {
        perror("mmap");
        exit(EXIT_FAILURE);
    }

    memset(fb, 0, FRAMEBUFFER_HEIGHT * bytes_per_row);

    int offsetx = 0;
    int offsety = 0;

    if(img.getWidth() <= FRAMEBUFFER_WIDTH && img.getHeight() <= FRAMEBUFFER_HEIGHT) {
        offsetx = (FRAMEBUFFER_WIDTH - img.getWidth()) / 2;
        offsety = (FRAMEBUFFER_HEIGHT - img.getHeight()) / 2;
    }

    for (unsigned int j = 0; j < std::min(FRAMEBUFFER_HEIGHT, img.getHeight()); j++) {
        RGBQUAD rgb;
        unsigned char* row = fb + bytes_per_row * (j + offsety);
        for (unsigned int i = 0; i < std::min(FRAMEBUFFER_WIDTH, img.getWidth()); i++) {
            img.getPixelColor(i, img.getHeight() - 1 - j, &rgb);
            unsigned char *pixel = row + (i + offsetx) * bytes_per_pixel;
            pixel[0] = rgb.rgbRed;
            pixel[1] = rgb.rgbGreen;
            pixel[2] = rgb.rgbBlue;
        }
    }

    if(1) {
        // Take what we wrote to memory and write it back out as a PPM file
        FILE *fp = fopen("debug_output.ppm", "wb");
        static unsigned char fb2[FRAMEBUFFER_WIDTH * FRAMEBUFFER_HEIGHT * 3];
        for(unsigned int j = 0; j < FRAMEBUFFER_HEIGHT; j++)
            for(unsigned int i = 0; i < FRAMEBUFFER_WIDTH; i++) {
                unsigned char *src, *dst;
                src = fb + j * bytes_per_row + i * bytes_per_pixel;
                dst = fb2 + (j * FRAMEBUFFER_WIDTH + i) * 3;
                dst[0] = src[0];
                dst[1] = src[1];
                dst[2] = src[2];
            }
        fprintf(fp, "P6 %d %d 255\n", FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT);
        fwrite(fb2, FRAMEBUFFER_WIDTH * FRAMEBUFFER_HEIGHT * 3, 1, fp); // XXX
        fclose(fp);
    }
}
<commit_msg>Add a test for getPixelColor()<commit_after>#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <fcntl.h>
// sudo apt-get install libfreeimageplus-dev
#include <FreeImagePlus.h>
#include <sys/mman.h>
#include <stdint.h>

void usage(char *argv[])
{
    fprintf(stderr, "\n");
    fprintf(stderr, "Usage: %s imagename fbaddress bytes_per_row [mode]\n", argv[0]);
    fprintf(stderr, "\t\"mode\" can be 8 for 8-byte pixels or 4 for 4 bytes or 3 for 3 bytes.\n");
    fprintf(stderr, "\tThe default for \"mode\" is 8.\n");
    fprintf(stderr, "\n");
    exit(EXIT_FAILURE);
}

static const unsigned int FRAMEBUFFER_WIDTH = 800;
static const unsigned int FRAMEBUFFER_HEIGHT = 480;

int main(int argc, char **argv)
{
    if(argc < 4 || argc > 5) {
        usage(argv);
    }

    unsigned int address = strtoul(argv[2], NULL, 0);
    unsigned int bytes_per_row = strtoul(argv[3], NULL, 0);

    int bytes_per_pixel;
    int mode = 8;

    if(argc > 4) {
        mode = atoi(argv[4]);
    }

    switch(mode) {
        case 3: bytes_per_pixel = 3; break;
        case 4: bytes_per_pixel = 4; break;
        case 8: bytes_per_pixel = 8; break;

        default:
            std::cerr << "unsupported mode " << mode << std::endl;
            exit(EXIT_FAILURE);
            break;
    }

    printf("Address = 0x%08X\n", address);
    printf("Bytes per row = %d\n", bytes_per_row);
    printf("Mode = %d (bytes per pixel = %d)\n", mode, bytes_per_pixel);
    FreeImage_Initialise();

    const char *filename = argv[1];

    fipImage img;
    if (!img.load(filename)) {
        std::cerr << "failed to load image " << filename << std::endl;
        exit(EXIT_FAILURE);
    }

    if (!img.convertTo32Bits()) {
	std::cerr << "Couldn't convert image to 32 bits " << filename << std::endl;
	exit(EXIT_FAILURE);
    }

    if(img.getImageType() == FIT_RGBF) {
        std::cerr << "image is incompatible type RGBF" << std::endl;
        exit(EXIT_FAILURE);
    }

    if(img.getImageType() != FIT_BITMAP) {
        std::cerr << "image is incompatible type " << img.getImageType() << std::endl;
        exit(EXIT_FAILURE);
    }

    int dev_mem = open("/dev/mem", O_RDWR);

    if(dev_mem == 0) {
        perror("open");
        exit(EXIT_FAILURE);
    }

    unsigned char *fb = (unsigned char *)mmap(0, FRAMEBUFFER_HEIGHT * bytes_per_row, PROT_READ | PROT_WRITE, /* MAP_NOCACHE | */ MAP_SHARED , dev_mem, address);

    if(fb == 0) {
        perror("mmap");
        exit(EXIT_FAILURE);
    }

    memset(fb, 0, FRAMEBUFFER_HEIGHT * bytes_per_row);

    int offsetx = 0;
    int offsety = 0;

    if(img.getWidth() <= FRAMEBUFFER_WIDTH && img.getHeight() <= FRAMEBUFFER_HEIGHT) {
        offsetx = (FRAMEBUFFER_WIDTH - img.getWidth()) / 2;
        offsety = (FRAMEBUFFER_HEIGHT - img.getHeight()) / 2;
    }

    RGBQUAD rgb;
    // Test that getPixelColor will succeed
    if(img.getPixelColor(0, 0, &rgb) == FALSE) {
        std::cerr << "getPixelColor() failed; incompatible image type" << std::endl;
        exit(EXIT_FAILURE);
    }

    for (unsigned int j = 0; j < std::min(FRAMEBUFFER_HEIGHT, img.getHeight()); j++) {
        unsigned char* row = fb + bytes_per_row * (j + offsety);
        for (unsigned int i = 0; i < std::min(FRAMEBUFFER_WIDTH, img.getWidth()); i++) {
            img.getPixelColor(i, img.getHeight() - 1 - j, &rgb);
            unsigned char *pixel = row + (i + offsetx) * bytes_per_pixel;
            pixel[0] = rgb.rgbRed;
            pixel[1] = rgb.rgbGreen;
            pixel[2] = rgb.rgbBlue;
        }
    }

    if(1) {
        // Take what we wrote to memory and write it back out as a PPM file
        FILE *fp = fopen("debug_output.ppm", "wb");
        static unsigned char fb2[FRAMEBUFFER_WIDTH * FRAMEBUFFER_HEIGHT * 3];
        for(unsigned int j = 0; j < FRAMEBUFFER_HEIGHT; j++)
            for(unsigned int i = 0; i < FRAMEBUFFER_WIDTH; i++) {
                unsigned char *src, *dst;
                src = fb + j * bytes_per_row + i * bytes_per_pixel;
                dst = fb2 + (j * FRAMEBUFFER_WIDTH + i) * 3;
                dst[0] = src[0];
                dst[1] = src[1];
                dst[2] = src[2];
            }
        fprintf(fp, "P6 %d %d 255\n", FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT);
        fwrite(fb2, FRAMEBUFFER_WIDTH * FRAMEBUFFER_HEIGHT * 3, 1, fp); // XXX
        fclose(fp);
    }
}
<|endoftext|>


<commit_before>/**
 * Copyright (C) 2015 Dato, Inc.
 * All rights reserved.
 *
 * This software may be modified and distributed under the terms
 * of the BSD license. See the LICENSE file for details.
 */
#include <process/process.hpp>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <climits>
#include <mutex>
#include <set>
#include <logger/logger.hpp>
#include <boost/filesystem.hpp>
#include <parallel/mutex.hpp>

namespace fs = boost::filesystem;

/*
 * We need to handle SIGCHLD here to support reaping of processes
 * marked for auto reaping. Basically, all we need to do really is to
 * loop through a set of procids registered by process::autoreap()
 * and call waitpid on them.
 *
 * The trick however is how to make this reentrant safe.
 *
 * To do so, the autoreap function must unregister the signal handler,
 * add the pid to the list of PIDs to reap, and then re-register the signal
 * handler.
 */
graphlab::mutex sigchld_handler_lock;
std::set<size_t> proc_ids_to_reap;

static void sigchld_handler(int sig) {
  // loop through the set of stuff to reap
  // and try to reap them
  auto iter = proc_ids_to_reap.begin();
  while (iter != proc_ids_to_reap.end()) {
    auto cur_iter = iter;
    ++iter;
    if (waitpid(*cur_iter, NULL, WNOHANG) > 0) {
      proc_ids_to_reap.erase(cur_iter);
    }
  }
}

/**
 * Install the SIGCHLD handler. Should be called
 * with sigchld_handler_lock_acquired
 */
static void install_sigchld_handler() {
  struct sigaction act;
  memset (&act, 0, sizeof(act));
  act.sa_handler = sigchld_handler;
  sigaction(SIGCHLD, &act, 0);
}

/**
 * Uninstalls the SIGCHLD handler. Should be called
 * with sigchld_handler_lock_acquired
 */
static void uninstall_sigchld_handler() {
  struct sigaction act;
  memset (&act, 0, sizeof(act));
  act.sa_handler = SIG_DFL;
  sigaction(SIGCHLD, &act, 0);
}

namespace graphlab
{

static const char** convert_args(std::string &cmd, const std::vector<std::string> &args) {
  // Convert args to c_str list
  // Size of filename of cmd + args + NULL
  const char** c_arglist = new const char*[args.size() + 2];
  size_t i = 0;
  c_arglist[i++] = cmd.c_str();
  for (const auto& arg: args) {
    c_arglist[i++] = arg.c_str();
  }
  c_arglist[i] = NULL;

  // std::cerr << "stuff: " << cmd << std::endl;
  /*
   * for(size_t i = 0; c_arglist[i] != NULL; ++i) {
   *   std::cerr << c_arglist[i] << std::endl;
   * }
   */

  return c_arglist;
}

bool process::popen(const std::string &cmd,
                    const std::vector<std::string> &args,
                    int child_write_fd) {
  // build pipe
  int fd[2];
  int& read_fd = fd[0];
  int& write_fd = fd[1];
  if (pipe(fd)) {
    logstream(LOG_ERROR) << "Error building pipe for process launch: " <<
        get_last_err_str(errno);
  }
  std::string cmd_tmp = cmd;
  const char **c_arglist = convert_args(cmd_tmp, args);

#ifdef __APPLE__
  pid_t pid = fork();
#else
  pid_t pid = vfork();
#endif

  if(pid < 0) {
    logstream(LOG_ERROR) << "Fail to fork process: " << strerror(errno) << std::endl;
    delete[] c_arglist;
    return false;
  } else if(pid == 0) {
    //***In child***
    close(read_fd);
    if((child_write_fd > -1) && (write_fd != child_write_fd)) {
      errno = 0;
      if(dup2(write_fd, child_write_fd) != child_write_fd) {
        _exit(1);
      }
      close(write_fd);
    }

    int exec_ret = execvp(&cmd[0], (char**)c_arglist);
    if(exec_ret == -1) {
      std::cerr << "Fail to exec: " << strerror(errno) << std::endl;
    }
    _exit(0);
  } else {
    m_launched = true;
    m_launched_with_popen = true;
    m_pid = pid;
    if(child_write_fd > -1) {
      m_read_handle = read_fd;
    } else {
      close(read_fd);
    }
    close(write_fd);
    delete[] c_arglist;
  }

  logstream(LOG_INFO) << "Launched process with pid: " << m_pid << std::endl;

  return true;
}

/**
 * A "generic" process launcher
 */
bool process::launch(const std::string &cmd,
                             const std::vector<std::string> &args) {
  std::string cmd_tmp = cmd;
  const char **c_arglist = convert_args(cmd_tmp, args);
#ifdef __APPLE__
  pid_t pid = fork();
#else
  pid_t pid = vfork();
#endif

  if(pid < 0) {
    logstream(LOG_ERROR) << "Fail to fork process: " << strerror(errno) << std::endl;
    delete[] c_arglist;
    return false;
  } else if(pid == 0) {
    int exec_ret = execvp(&cmd[0], (char**)c_arglist);
    if(exec_ret == -1) {
      std::cerr << "Fail to exec: " << strerror(errno) << std::endl;
    }
    _exit(0);
  } else {
    m_launched = true;
    m_pid = pid;
    delete[] c_arglist;
  }

  logstream(LOG_INFO) << "Launched process with pid: " << m_pid << std::endl;

  return true;
}

ssize_t process::read_from_child(void *buf, size_t count) {
  if(!m_launched)
    log_and_throw("No process launched!");
  if(!m_launched_with_popen)
    log_and_throw("Cannot read from process launched without a pipe!");
  if(m_read_handle == -1)
    log_and_throw("Cannot read from child, no pipe initialized. "
        "Specify child_write_fd on launch to do this.");
  return read(m_read_handle, buf, count);
}

bool process::kill(bool async) {
  if(!m_launched)
    log_and_throw("No process launched!");

  ::kill(m_pid, SIGKILL);

  if(!async) {
    pid_t wp_rc = waitpid(m_pid, NULL, 0);
    if(wp_rc == -1) {
      auto err_str = get_last_err_str(errno);
      logstream(LOG_INFO) << "Cannot kill process: " << err_str << std::endl;
      return false;
    }
  }

  return true;
}

bool process::exists() {
  if(!m_launched)
    log_and_throw("No process launched!");
  int status;
  auto wp_ret = waitpid(m_pid, &status, WNOHANG);
  if(wp_ret == -1) {
    logstream(LOG_WARNING) << "Failed while checking for existence of process "
      << m_pid << ": " << strerror(errno) << std::endl;
  } else if(wp_ret == 0) {
    return true;
  }

  return false;
}

int process::get_return_code() {
  int status;
  auto wp_ret = waitpid(m_pid, &status, WNOHANG);
  if(wp_ret == -1) {
    return INT_MAX;
  } else if(wp_ret == 0) {
    return INT_MIN;
  } else if(wp_ret != m_pid) {
    return INT_MAX;
  }

  return WEXITSTATUS(status);
}

void process::close_read_pipe() {
  if(!m_launched)
    log_and_throw("No process launched!");
  if(!m_launched_with_popen)
    log_and_throw("Cannot close pipe from process when launched without a pipe!");
  if(m_read_handle == -1)
    log_and_throw("Cannot close pipe from child, no pipe initialized.");
  if(m_read_handle > -1) {
    close(m_read_handle);
    m_read_handle = -1;
  }
}

size_t process::get_pid() {
  return size_t(m_pid);
}

process::~process() {
  if(m_read_handle > -1)
    close(m_read_handle);
}

void process::autoreap() {
  if (m_pid) {
    std::lock_guard<graphlab::mutex> guard(sigchld_handler_lock);
    uninstall_sigchld_handler();
    proc_ids_to_reap.insert(m_pid);
    install_sigchld_handler();
  }
}

} // namespace graphlab
<commit_msg>Fix ephemeral crash/hang on termination due to sigchild handler<commit_after>/**
 * Copyright (C) 2015 Dato, Inc.
 * All rights reserved.
 *
 * This software may be modified and distributed under the terms
 * of the BSD license. See the LICENSE file for details.
 */
#include <process/process.hpp>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>
#include <climits>
#include <mutex>
#include <set>
#include <logger/logger.hpp>
#include <boost/filesystem.hpp>
#include <parallel/mutex.hpp>
#include <pthread.h>

namespace fs = boost::filesystem;

/*
 * We need to handle SIGCHLD here to support reaping of processes
 * marked for auto reaping. Basically, all we need to do really is to
 * loop through a set of procids registered by process::autoreap()
 * and call waitpid on them.
 *
 * The trick however is how to make this reentrant safe.
 *
 * To do so, the autoreap function must unregister the signal handler,
 * add the pid to the list of PIDs to reap, and then re-register the signal
 * handler.
 */
graphlab::mutex sigchld_handler_lock;

// This is an intentional leak of raw pointer because it is used on program termination.
static std::set<size_t>* proc_ids_to_reap;
static pthread_once_t proc_ids_to_reap_is_initialized = PTHREAD_ONCE_INIT;
static void init_proc_ids_to_reap() { proc_ids_to_reap = new std::set<size_t>(); }

static void sigchld_handler(int sig) {
  // loop through the set of stuff to reap
  // and try to reap them
  auto iter = proc_ids_to_reap->begin();
  while (iter != proc_ids_to_reap->end()) {
    if (waitpid(*iter, NULL, WNOHANG) > 0) {
      iter = proc_ids_to_reap->erase(iter);
    } else {
      ++iter;
    }
  }
}

/**
 * Install the SIGCHLD handler. Should be called
 * with sigchld_handler_lock_acquired
 */
static void install_sigchld_handler() {
  struct sigaction act;
  memset (&act, 0, sizeof(act));
  act.sa_handler = sigchld_handler;
  sigaction(SIGCHLD, &act, 0);
}

/**
 * Uninstalls the SIGCHLD handler. Should be called
 * with sigchld_handler_lock_acquired
 */
static void uninstall_sigchld_handler() {
  struct sigaction act;
  memset (&act, 0, sizeof(act));
  act.sa_handler = SIG_DFL;
  sigaction(SIGCHLD, &act, 0);
}

namespace graphlab
{

static const char** convert_args(std::string &cmd, const std::vector<std::string> &args) {
  // Convert args to c_str list
  // Size of filename of cmd + args + NULL
  const char** c_arglist = new const char*[args.size() + 2];
  size_t i = 0;
  c_arglist[i++] = cmd.c_str();
  for (const auto& arg: args) {
    c_arglist[i++] = arg.c_str();
  }
  c_arglist[i] = NULL;

  // std::cerr << "stuff: " << cmd << std::endl;
  /*
   * for(size_t i = 0; c_arglist[i] != NULL; ++i) {
   *   std::cerr << c_arglist[i] << std::endl;
   * }
   */

  return c_arglist;
}

bool process::popen(const std::string &cmd,
                    const std::vector<std::string> &args,
                    int child_write_fd) {
  // build pipe
  int fd[2];
  int& read_fd = fd[0];
  int& write_fd = fd[1];
  if (pipe(fd)) {
    logstream(LOG_ERROR) << "Error building pipe for process launch: " <<
        get_last_err_str(errno);
  }
  std::string cmd_tmp = cmd;
  const char **c_arglist = convert_args(cmd_tmp, args);

#ifdef __APPLE__
  pid_t pid = fork();
#else
  pid_t pid = vfork();
#endif

  if(pid < 0) {
    logstream(LOG_ERROR) << "Fail to fork process: " << strerror(errno) << std::endl;
    delete[] c_arglist;
    return false;
  } else if(pid == 0) {
    //***In child***
    close(read_fd);
    if((child_write_fd > -1) && (write_fd != child_write_fd)) {
      errno = 0;
      if(dup2(write_fd, child_write_fd) != child_write_fd) {
        _exit(1);
      }
      close(write_fd);
    }

    int exec_ret = execvp(&cmd[0], (char**)c_arglist);
    if(exec_ret == -1) {
      std::cerr << "Fail to exec: " << strerror(errno) << std::endl;
    }
    _exit(0);
  } else {
    m_launched = true;
    m_launched_with_popen = true;
    m_pid = pid;
    if(child_write_fd > -1) {
      m_read_handle = read_fd;
    } else {
      close(read_fd);
    }
    close(write_fd);
    delete[] c_arglist;
  }

  logstream(LOG_INFO) << "Launched process with pid: " << m_pid << std::endl;

  return true;
}

/**
 * A "generic" process launcher
 */
bool process::launch(const std::string &cmd,
                             const std::vector<std::string> &args) {
  std::string cmd_tmp = cmd;
  const char **c_arglist = convert_args(cmd_tmp, args);
#ifdef __APPLE__
  pid_t pid = fork();
#else
  pid_t pid = vfork();
#endif

  if(pid < 0) {
    logstream(LOG_ERROR) << "Fail to fork process: " << strerror(errno) << std::endl;
    delete[] c_arglist;
    return false;
  } else if(pid == 0) {
    int exec_ret = execvp(&cmd[0], (char**)c_arglist);
    if(exec_ret == -1) {
      std::cerr << "Fail to exec: " << strerror(errno) << std::endl;
    }
    _exit(0);
  } else {
    m_launched = true;
    m_pid = pid;
    delete[] c_arglist;
  }

  logstream(LOG_INFO) << "Launched process with pid: " << m_pid << std::endl;

  return true;
}

ssize_t process::read_from_child(void *buf, size_t count) {
  if(!m_launched)
    log_and_throw("No process launched!");
  if(!m_launched_with_popen)
    log_and_throw("Cannot read from process launched without a pipe!");
  if(m_read_handle == -1)
    log_and_throw("Cannot read from child, no pipe initialized. "
        "Specify child_write_fd on launch to do this.");
  return read(m_read_handle, buf, count);
}

bool process::kill(bool async) {
  if(!m_launched)
    log_and_throw("No process launched!");

  ::kill(m_pid, SIGKILL);

  if(!async) {
    pid_t wp_rc = waitpid(m_pid, NULL, 0);
    if(wp_rc == -1) {
      auto err_str = get_last_err_str(errno);
      logstream(LOG_INFO) << "Cannot kill process: " << err_str << std::endl;
      return false;
    }
  }

  return true;
}

bool process::exists() {
  if(!m_launched)
    log_and_throw("No process launched!");
  int status;
  auto wp_ret = waitpid(m_pid, &status, WNOHANG);
  if(wp_ret == -1) {
    logstream(LOG_WARNING) << "Failed while checking for existence of process "
      << m_pid << ": " << strerror(errno) << std::endl;
  } else if(wp_ret == 0) {
    return true;
  }

  return false;
}

int process::get_return_code() {
  int status;
  auto wp_ret = waitpid(m_pid, &status, WNOHANG);
  if(wp_ret == -1) {
    return INT_MAX;
  } else if(wp_ret == 0) {
    return INT_MIN;
  } else if(wp_ret != m_pid) {
    return INT_MAX;
  }

  return WEXITSTATUS(status);
}

void process::close_read_pipe() {
  if(!m_launched)
    log_and_throw("No process launched!");
  if(!m_launched_with_popen)
    log_and_throw("Cannot close pipe from process when launched without a pipe!");
  if(m_read_handle == -1)
    log_and_throw("Cannot close pipe from child, no pipe initialized.");
  if(m_read_handle > -1) {
    close(m_read_handle);
    m_read_handle = -1;
  }
}

size_t process::get_pid() {
  return size_t(m_pid);
}

process::~process() {
  if(m_read_handle > -1)
    close(m_read_handle);
}

void process::autoreap() {
  if (m_pid) {
    std::lock_guard<graphlab::mutex> guard(sigchld_handler_lock);
    pthread_once(&proc_ids_to_reap_is_initialized, init_proc_ids_to_reap);
    ASSERT_MSG(proc_ids_to_reap != NULL, "proc_ids_to_reap not initialized");
    uninstall_sigchld_handler();
    proc_ids_to_reap->insert(m_pid);
    install_sigchld_handler();
  }
}

} // namespace graphlab
<|endoftext|>


<commit_before>/* linbox/algorithms/gauss-solve.inl
 * Copyright (C) LinBox 2008
 *
 * Written by Jean-Guillaume Dumas <Jean-Guillaume.Dumas@imag.fr>
 * Time-stamp: <18 Jun 10 15:08:49 Jean-Guillaume.Dumas@imag.fr>
 *
 * See COPYING for license information.
 */

#ifndef __GAUSS_NULLSPACE_INL
#define __GAUSS_NULLSPACE_INL

#include "linbox/algorithms/gauss.h"
#include "linbox/algorithms/triangular-solve.h"
#include "linbox/blackbox/permutation.h"
#include "linbox/vector/sparse.h"

namespace LinBox
{

        // U is supposed full rank upper triangular
    template <class _Field>
    template <class Matrix, class Perm, class Block> inline Block&
    GaussDomain<_Field>::nullspacebasis(Block& x, unsigned long rank, const Matrix& U, const Perm& P)  const {
        if (rank == 0) {
            for(size_t i=0; i<U.coldim(); ++i)
                x.setEntry(i,i,_F.one);
        } else {
            unsigned long nullity = U.coldim()-rank;
            if (nullity != 0) {
                    // compute U2T s.t. U = [ U1 | -U2T^T ]
                Matrix U2T(_F,nullity,rank);

                for(typename Matrix::ConstRawIndexedIterator uit=U.rawIndexedBegin();
                    uit != U.rawIndexedEnd(); ++uit) {
                    if (uit.colIndex() >= rank)
                        U2T.setEntry(uit.colIndex()-rank,uit.rowIndex(),uit.value());
                }
                for(typename Matrix::RawIterator u2it=U2T.rawBegin();
                    u2it != U2T.rawEnd(); ++u2it)
                    _F.negin(*u2it);

                    // Compute the basis vector by vector
                typedef Sparse_Vector< typename _Field::Element > SparseVect;
                for(size_t i=0; i<nullity; ++i) {
                    SparseVect W1Ti;
                        // Solve for upper part of basis
                    upperTriangularSparseSolve(W1Ti, rank, U, U2T[i]);
                        // Add identity for lower part
                    W1Ti.push_back( typename SparseVect::Element(rank+i, _F.one ) );

                    for(size_t j=0; j<W1Ti.size(); ++j) {
                            // P.applyTranspose(x[i],W1T[i]);
                            // Transposein(x)
                        x.setEntry( P.getStorage()[ W1Ti[j].first ], i, W1Ti[j].second );
                    }
                }
            }
        }
// x.write( std::cerr << "X:=", FORMAT_MAPLE ) << ';' << std::endl;
        return x;
    }

    template <class Matrix>
    inline bool nextnonzero(size_t& k, size_t Ni, const Matrix& A) {
        for(++k; k<Ni; ++k)
            if (A[k].size() > 0) return true;
        return false;
    }

        // Matrix A is upper triangularized
    template <class _Field>
    template <class Matrix, class Block> inline Block&
    GaussDomain<_Field>::nullspacebasisin(Block& x, Matrix& A)  const {
        typename Field::Element det;
        unsigned long rank;
        size_t Ni(A.rowdim()),Nj(A.coldim());

        Permutation<Field> P(Nj,_F);

// A.write( std::cerr << "A:=", FORMAT_MAPLE ) << ';' << std::endl;
        this->InPlaceLinearPivoting(rank, det, A, P, Ni, Nj );

// P.write( std::cerr << "P:=", FORMAT_MAPLE ) << ';' << std::endl;
// A.write( std::cerr << "Ua:=", FORMAT_MAPLE ) << ';' << std::endl;

        for(size_t i=0; i< Ni; ++i) {
            if (A[i].size() == 0) {
                size_t j(i);
                if (nextnonzero(j,Ni,A)) {
                    A[i] = A[j];
                    A[j].resize(0);
                } else {
                    break;
                }
            }
        }

// A.write( std::cerr << "Ub:=", FORMAT_MAPLE ) << ';' << std::endl;

        return this->nullspacebasis(x, rank, A, P);
    }

    template <class _Field>
    template <class Matrix, class Block> inline Block&
    GaussDomain<_Field>::nullspacebasis(Block& x, const Matrix& A)  const {
        SparseMatrix<Field, typename LinBox::Vector<Field>::SparseSeq> A1 (A);
        return this->nullspacebasisin(x, A1);
    }

} // namespace LinBox

#endif // __GAUSS_NULLSPACE_INL
<commit_msg>added include sparse.h<commit_after>/* linbox/algorithms/gauss-solve.inl
 * Copyright (C) LinBox 2008
 *
 * Written by Jean-Guillaume Dumas <Jean-Guillaume.Dumas@imag.fr>
 * Time-stamp: <21 Jun 10 14:43:11 Jean-Guillaume.Dumas@imag.fr>
 *
 * See COPYING for license information.
 */

#ifndef __GAUSS_NULLSPACE_INL
#define __GAUSS_NULLSPACE_INL

#include "linbox/blackbox/sparse.h"
#include "linbox/algorithms/gauss.h"
#include "linbox/algorithms/triangular-solve.h"
#include "linbox/blackbox/permutation.h"
#include "linbox/vector/sparse.h"

namespace LinBox
{

        // U is supposed full rank upper triangular
    template <class _Field>
    template <class Matrix, class Perm, class Block> inline Block&
    GaussDomain<_Field>::nullspacebasis(Block& x, unsigned long rank, const Matrix& U, const Perm& P)  const {
        if (rank == 0) {
            for(size_t i=0; i<U.coldim(); ++i)
                x.setEntry(i,i,_F.one);
        } else {
            unsigned long nullity = U.coldim()-rank;
            if (nullity != 0) {
                    // compute U2T s.t. U = [ U1 | -U2T^T ]
                Matrix U2T(_F,nullity,rank);

                for(typename Matrix::ConstRawIndexedIterator uit=U.rawIndexedBegin();
                    uit != U.rawIndexedEnd(); ++uit) {
                    if (uit.colIndex() >= rank)
                        U2T.setEntry(uit.colIndex()-rank,uit.rowIndex(),uit.value());
                }
                for(typename Matrix::RawIterator u2it=U2T.rawBegin();
                    u2it != U2T.rawEnd(); ++u2it)
                    _F.negin(*u2it);

                    // Compute the basis vector by vector
                typedef Sparse_Vector< typename _Field::Element > SparseVect;
                for(size_t i=0; i<nullity; ++i) {
                    SparseVect W1Ti;
                        // Solve for upper part of basis
                    upperTriangularSparseSolve(W1Ti, rank, U, U2T[i]);
                        // Add identity for lower part
                    W1Ti.push_back( typename SparseVect::Element(rank+i, _F.one ) );

                    for(size_t j=0; j<W1Ti.size(); ++j) {
                            // P.applyTranspose(x[i],W1T[i]);
                            // Transposein(x)
                        x.setEntry( P.getStorage()[ W1Ti[j].first ], i, W1Ti[j].second );
                    }
                }
            }
        }
// x.write( std::cerr << "X:=", FORMAT_MAPLE ) << ';' << std::endl;
        return x;
    }

    template <class Matrix>
    inline bool nextnonzero(size_t& k, size_t Ni, const Matrix& A) {
        for(++k; k<Ni; ++k)
            if (A[k].size() > 0) return true;
        return false;
    }

        // Matrix A is upper triangularized
    template <class _Field>
    template <class Matrix, class Block> inline Block&
    GaussDomain<_Field>::nullspacebasisin(Block& x, Matrix& A)  const {
        typename Field::Element det;
        unsigned long rank;
        size_t Ni(A.rowdim()),Nj(A.coldim());

        Permutation<Field> P(Nj,_F);

// A.write( std::cerr << "A:=", FORMAT_MAPLE ) << ';' << std::endl;
        this->InPlaceLinearPivoting(rank, det, A, P, Ni, Nj );

// P.write( std::cerr << "P:=", FORMAT_MAPLE ) << ';' << std::endl;
// A.write( std::cerr << "Ua:=", FORMAT_MAPLE ) << ';' << std::endl;

        for(size_t i=0; i< Ni; ++i) {
            if (A[i].size() == 0) {
                size_t j(i);
                if (nextnonzero(j,Ni,A)) {
                    A[i] = A[j];
                    A[j].resize(0);
                } else {
                    break;
                }
            }
        }

// A.write( std::cerr << "Ub:=", FORMAT_MAPLE ) << ';' << std::endl;

        return this->nullspacebasis(x, rank, A, P);
    }

    template <class _Field>
    template <class Matrix, class Block> inline Block&
    GaussDomain<_Field>::nullspacebasis(Block& x, const Matrix& A)  const {
        SparseMatrix<Field, typename LinBox::Vector<Field>::SparseSeq> A1 (A);
        return this->nullspacebasisin(x, A1);
    }

} // namespace LinBox

#endif // __GAUSS_NULLSPACE_INL
<|endoftext|>


<commit_before>// Copyright (c) 2019 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <Rosetta/Commons/Utils.hpp>
#include <Rosetta/Models/HeroPower.hpp>
#include <Rosetta/Models/Player.hpp>
#include <Rosetta/Policies/Policy.hpp>
#include <Rosetta/Tasks/PlayerTasks/AttackTask.hpp>
#include <Rosetta/Tasks/PlayerTasks/EndTurnTask.hpp>
#include <Rosetta/Tasks/PlayerTasks/PlayCardTask.hpp>

namespace RosettaStone
{
Player::Player() : playerID(USER_INVALID)
{
    m_deckZone = new DeckZone(this);
    m_fieldZone = new FieldZone(this);
    m_graveyardZone = new GraveyardZone(this);
    m_handZone = new HandZone(this);
    m_setasideZone = new SetasideZone(this);
}

Player::~Player()
{
    delete m_setasideZone;
    delete m_handZone;
    delete m_graveyardZone;
    delete m_fieldZone;
    delete m_deckZone;

    delete m_hero;
}

Game* Player::GetGame() const
{
    return m_game;
}

void Player::SetGame(Game* game)
{
    m_game = game;
}

FieldZone& Player::GetFieldZone() const
{
    return *m_fieldZone;
}

DeckZone& Player::GetDeckZone() const
{
    return *m_deckZone;
}

GraveyardZone& Player::GetGraveyardZone() const
{
    return *m_graveyardZone;
}

HandZone& Player::GetHandZone() const
{
    return *m_handZone;
}

SecretZone& Player::GetSecretZone() const
{
    return *m_secretZone;
}

SetasideZone& Player::GetSetasideZone() const
{
    return *m_setasideZone;
}

Hero* Player::GetHero() const
{
    return m_hero;
}

int Player::GetGameTag(GameTag tag) const
{
    if (m_gameTags.find(tag) == m_gameTags.end())
    {
        return 0;
    }

    return m_gameTags.at(tag);
}

void Player::SetGameTag(GameTag tag, int value)
{
    m_gameTags.insert_or_assign(tag, value);
}

int Player::GetTotalMana() const
{
    return GetGameTag(GameTag::RESOURCES);
}

void Player::SetTotalMana(int amount)
{
    SetGameTag(GameTag::RESOURCES, amount);
}

int Player::GetUsedMana() const
{
    return GetGameTag(GameTag::RESOURCES_USED);
}

void Player::SetUsedMana(int amount)
{
    SetGameTag(GameTag::RESOURCES_USED, amount);
}

int Player::GetTemporaryMana() const
{
    return GetGameTag(GameTag::TEMP_RESOURCES);
}

void Player::SetTemporaryMana(int amount)
{
    SetGameTag(GameTag::TEMP_RESOURCES, amount);
}

int Player::GetOverloadOwed() const
{
    return GetGameTag(GameTag::OVERLOAD_OWED);
}

void Player::SetOverloadOwed(int amount)
{
    SetGameTag(GameTag::OVERLOAD_OWED, amount);
}

int Player::GetOverloadLocked() const
{
    return GetGameTag(GameTag::OVERLOAD_LOCKED);
}

void Player::SetOverloadLocked(int amount)
{
    SetGameTag(GameTag::OVERLOAD_LOCKED, amount);
}

int Player::GetRemainingMana() const
{
    return GetTotalMana() + GetTemporaryMana() -
           (GetUsedMana() + GetOverloadLocked());
}

bool Player::IsComboActive() const
{
    return GetGameTag(GameTag::COMBO_ACTIVE) == 1;
}

void Player::SetComboActive(bool isActive)
{
    SetGameTag(GameTag::COMBO_ACTIVE, isActive ? 1 : 0);
}

ITask* Player::GetNextAction()
{
    ITask* ret;

    do
    {
        // Get next action as TaskID
        // ex) TaskID::END_TURN, TaskID::ATTACK, TaskID::PLAY_CARD
        TaskMeta next = policy->Next(*m_game);
        // Get requirements for proper action
        TaskMeta req = policy->Require(*this, next.GetID());

        ret = GetTaskByAction(next, req);
    } while (ret == nullptr);

    return ret;
}

void Player::AddHeroAndPower(Card&& heroCard, Card&& powerCard)
{
    m_hero =
        dynamic_cast<Hero*>(Entity::GetFromCard(*this, std::move(heroCard)));
    m_hero->heroPower = dynamic_cast<HeroPower*>(
        Entity::GetFromCard(*this, std::move(powerCard)));
}

ITask* Player::GetTaskByAction(TaskMeta& next, TaskMeta& req)
{
    SizedPtr<Entity*> list = req.GetObject<SizedPtr<Entity*>>();

    switch (next.GetID())
    {
        case TaskID::ATTACK:
        {
            if (list.size() >= 2)
            {
                Entity* source = list[0];
                Entity* target = list[1];
                return new PlayerTasks::AttackTask(source, target);
            }

            return nullptr;
        }
        case TaskID::PLAY_CARD:
        {
            // If requirement doesn't satisfy
            if (list.size() < 1)
            {
                return nullptr;
            }

            Entity* source = list[0];
            Entity* target = list.size() >= 2 ? list[1] : nullptr;

            return new PlayerTasks::PlayCardTask(source, target);
        }
        case TaskID::END_TURN:
        {
            return new PlayerTasks::EndTurnTask();
        }
        default:
            return nullptr;
    }
}
}  // namespace RosettaStone
<commit_msg>fix: Correct crash problem due to 'nullptr'<commit_after>// Copyright (c) 2019 Chris Ohk, Youngjoong Kim, SeungHyun Jeon

// We are making my contributions/submissions to this project solely in our
// personal capacity and are not conveying any rights to any intellectual
// property of any third parties.

#include <Rosetta/Commons/Utils.hpp>
#include <Rosetta/Models/HeroPower.hpp>
#include <Rosetta/Models/Player.hpp>
#include <Rosetta/Policies/Policy.hpp>
#include <Rosetta/Tasks/PlayerTasks/AttackTask.hpp>
#include <Rosetta/Tasks/PlayerTasks/EndTurnTask.hpp>
#include <Rosetta/Tasks/PlayerTasks/PlayCardTask.hpp>

namespace RosettaStone
{
Player::Player() : playerID(USER_INVALID)
{
    m_deckZone = new DeckZone(this);
    m_fieldZone = new FieldZone(this);
    m_graveyardZone = new GraveyardZone(this);
    m_handZone = new HandZone(this);
    m_secretZone = new SecretZone(this);
    m_setasideZone = new SetasideZone(this);
}

Player::~Player()
{
    delete m_setasideZone;
    delete m_secretZone;
    delete m_handZone;
    delete m_graveyardZone;
    delete m_fieldZone;
    delete m_deckZone;

    delete m_hero;
}

Game* Player::GetGame() const
{
    return m_game;
}

void Player::SetGame(Game* game)
{
    m_game = game;
}

FieldZone& Player::GetFieldZone() const
{
    return *m_fieldZone;
}

DeckZone& Player::GetDeckZone() const
{
    return *m_deckZone;
}

GraveyardZone& Player::GetGraveyardZone() const
{
    return *m_graveyardZone;
}

HandZone& Player::GetHandZone() const
{
    return *m_handZone;
}

SecretZone& Player::GetSecretZone() const
{
    return *m_secretZone;
}

SetasideZone& Player::GetSetasideZone() const
{
    return *m_setasideZone;
}

Hero* Player::GetHero() const
{
    return m_hero;
}

int Player::GetGameTag(GameTag tag) const
{
    if (m_gameTags.find(tag) == m_gameTags.end())
    {
        return 0;
    }

    return m_gameTags.at(tag);
}

void Player::SetGameTag(GameTag tag, int value)
{
    m_gameTags.insert_or_assign(tag, value);
}

int Player::GetTotalMana() const
{
    return GetGameTag(GameTag::RESOURCES);
}

void Player::SetTotalMana(int amount)
{
    SetGameTag(GameTag::RESOURCES, amount);
}

int Player::GetUsedMana() const
{
    return GetGameTag(GameTag::RESOURCES_USED);
}

void Player::SetUsedMana(int amount)
{
    SetGameTag(GameTag::RESOURCES_USED, amount);
}

int Player::GetTemporaryMana() const
{
    return GetGameTag(GameTag::TEMP_RESOURCES);
}

void Player::SetTemporaryMana(int amount)
{
    SetGameTag(GameTag::TEMP_RESOURCES, amount);
}

int Player::GetOverloadOwed() const
{
    return GetGameTag(GameTag::OVERLOAD_OWED);
}

void Player::SetOverloadOwed(int amount)
{
    SetGameTag(GameTag::OVERLOAD_OWED, amount);
}

int Player::GetOverloadLocked() const
{
    return GetGameTag(GameTag::OVERLOAD_LOCKED);
}

void Player::SetOverloadLocked(int amount)
{
    SetGameTag(GameTag::OVERLOAD_LOCKED, amount);
}

int Player::GetRemainingMana() const
{
    return GetTotalMana() + GetTemporaryMana() -
           (GetUsedMana() + GetOverloadLocked());
}

bool Player::IsComboActive() const
{
    return GetGameTag(GameTag::COMBO_ACTIVE) == 1;
}

void Player::SetComboActive(bool isActive)
{
    SetGameTag(GameTag::COMBO_ACTIVE, isActive ? 1 : 0);
}

ITask* Player::GetNextAction()
{
    ITask* ret;

    do
    {
        // Get next action as TaskID
        // ex) TaskID::END_TURN, TaskID::ATTACK, TaskID::PLAY_CARD
        TaskMeta next = policy->Next(*m_game);
        // Get requirements for proper action
        TaskMeta req = policy->Require(*this, next.GetID());

        ret = GetTaskByAction(next, req);
    } while (ret == nullptr);

    return ret;
}

void Player::AddHeroAndPower(Card&& heroCard, Card&& powerCard)
{
    m_hero =
        dynamic_cast<Hero*>(Entity::GetFromCard(*this, std::move(heroCard)));
    m_hero->heroPower = dynamic_cast<HeroPower*>(
        Entity::GetFromCard(*this, std::move(powerCard)));
}

ITask* Player::GetTaskByAction(TaskMeta& next, TaskMeta& req)
{
    SizedPtr<Entity*> list = req.GetObject<SizedPtr<Entity*>>();

    switch (next.GetID())
    {
        case TaskID::ATTACK:
        {
            if (list.size() >= 2)
            {
                Entity* source = list[0];
                Entity* target = list[1];
                return new PlayerTasks::AttackTask(source, target);
            }

            return nullptr;
        }
        case TaskID::PLAY_CARD:
        {
            // If requirement doesn't satisfy
            if (list.size() < 1)
            {
                return nullptr;
            }

            Entity* source = list[0];
            Entity* target = list.size() >= 2 ? list[1] : nullptr;

            return new PlayerTasks::PlayCardTask(source, target);
        }
        case TaskID::END_TURN:
        {
            return new PlayerTasks::EndTurnTask();
        }
        default:
            return nullptr;
    }
}
}  // namespace RosettaStone
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: buttonnavigationhandler.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 20:05:21 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef EXTENSIONS_SOURCE_PROPCTRLR_BUTTONNAVIGATIONHANDLER_HXX
#define EXTENSIONS_SOURCE_PROPCTRLR_BUTTONNAVIGATIONHANDLER_HXX

#ifndef EXTENSIONS_SOURCE_PROPCTRLR_PROPERTYHANDLER_HXX
#include "propertyhandler.hxx"
#endif

/** === begin UNO includes === **/
/** === end UNO includes === **/

//........................................................................
namespace pcr
{
//........................................................................

    //====================================================================
    //= ButtonNavigationHandler
    //====================================================================
    /** a property handler for any virtual string properties
    */
    class ButtonNavigationHandler : public PropertyHandler
    {
    public:
        // HandlerFactory
        inline static IPropertyHandler* Create(
            const ::com::sun::star::uno::Reference< ::com::sun::star::lang::XMultiServiceFactory >& _rxORB,
            const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxIntrospectee,
            const ::com::sun::star::uno::Reference< ::com::sun::star::frame::XModel >& _rxContextDocument,
            const ::com::sun::star::uno::Reference< ::com::sun::star::script::XTypeConverter >& _rxTypeConverter
        )
        {
            return new ButtonNavigationHandler( _rxIntrospectee, _rxTypeConverter );
        }

        static bool    isNavigationCapableButton( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxComponent );

    protected:
        ButtonNavigationHandler(
            const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxIntrospectee,
            const ::com::sun::star::uno::Reference< ::com::sun::star::script::XTypeConverter >& _rxTypeConverter
        );
        ~ButtonNavigationHandler();

    protected:
        // IPropertyHandler overriables
        virtual ::com::sun::star::uno::Any              SAL_CALL getPropertyValue( PropertyId _nPropId, bool _bLazy = true ) const;
        virtual void                                    SAL_CALL setPropertyValue( PropertyId _nPropId, const ::com::sun::star::uno::Any& _rValue );
        virtual ::com::sun::star::beans::PropertyState  SAL_CALL getPropertyState( PropertyId _nPropId ) const;

        // PropertyHandler overridables
        virtual ::std::vector< ::com::sun::star::beans::Property >
                                                        SAL_CALL implDescribeSupportedProperties() const;
    };

//........................................................................
} // namespace pcr
//........................................................................

#endif // EXTENSIONS_SOURCE_PROPCTRLR_BUTTONNAVIGATIONHANDLER_HXX

<commit_msg>INTEGRATION: CWS pbrwuno (1.3.130); FILE MERGED 2005/11/02 11:43:36 fs 1.3.130.11: #i10000# exception specifications 2005/10/25 11:52:40 fs 1.3.130.10: #i53095# some exception specifications, and some conceptual changes for multiple handlers supporting the same property 2005/10/25 07:13:06 fs 1.3.130.9: #i53095# knitting lose ends (amongst others, make the handlers available as service) 2005/10/24 08:41:38 fs 1.3.130.8: start making the handlers full-fledged components, with using a new infrastructure replacing extensions/source/inc/componentmodule.* 2005/10/13 13:00:58 fs 1.3.130.7: #i53095# introduce an XObjectInspector/Model 2005/10/11 13:28:50 fs 1.3.130.6: #i53095# phase 3: introduced XPropertyHandler and XObjectInspectorUI same open issues as in previous phase (plus probably some more, since not everything is tested, yet :-\) 2005/10/05 06:51:03 fs 1.3.130.5: RESYNC: (1.3-1.4); FILE MERGED 2005/08/18 12:44:26 fs 1.3.130.4: #i53095#, phase 2<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: buttonnavigationhandler.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: vg $ $Date: 2006-03-14 11:18:50 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef EXTENSIONS_SOURCE_PROPCTRLR_BUTTONNAVIGATIONHANDLER_HXX
#define EXTENSIONS_SOURCE_PROPCTRLR_BUTTONNAVIGATIONHANDLER_HXX

#ifndef EXTENSIONS_SOURCE_PROPCTRLR_PROPERTYHANDLER_HXX
#include "propertyhandler.hxx"
#endif

/** === begin UNO includes === **/
/** === end UNO includes === **/

//........................................................................
namespace pcr
{
//........................................................................

    //====================================================================
    //= ButtonNavigationHandler
    //====================================================================
    class ButtonNavigationHandler;
    typedef HandlerComponentBase< ButtonNavigationHandler > ButtonNavigationHandler_Base;
    /** a property handler for any virtual string properties
    */
    class ButtonNavigationHandler : public ButtonNavigationHandler_Base
    {
    public:
        ButtonNavigationHandler(
            const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& _rxContext
        );
        static ::rtl::OUString SAL_CALL getImplementationName_static(  ) throw (::com::sun::star::uno::RuntimeException);
        static ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static(  ) throw (::com::sun::star::uno::RuntimeException);

    protected:
        ~ButtonNavigationHandler();

        static bool    isNavigationCapableButton( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& _rxComponent );

    protected:
        // XPropertyHandler overriables
        virtual ::com::sun::star::uno::Any              SAL_CALL getPropertyValue( const ::rtl::OUString& _rPropertyName ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);
        virtual void                                    SAL_CALL setPropertyValue( const ::rtl::OUString& _rPropertyName, const ::com::sun::star::uno::Any& _rValue ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::beans::PropertyState  SAL_CALL getPropertyState( const ::rtl::OUString& _rPropertyName ) throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);

        // PropertyHandler overridables
        virtual ::com::sun::star::uno::Sequence< ::com::sun::star::beans::Property >
                                                        SAL_CALL doDescribeSupportedProperties() const;
    };

//........................................................................
} // namespace pcr
//........................................................................

#endif // EXTENSIONS_SOURCE_PROPCTRLR_BUTTONNAVIGATIONHANDLER_HXX

<|endoftext|>


<commit_before>#include <cstring>

#include "Wav.hpp"
#include "common/Exception.hpp"
#include "common/Convert.hpp"
#include "common/Log.hpp"

Wav::Wav(const char *fileName)
{
	this->open(fileName);
}

Wav::~Wav()
{
	this->close();
}

void Wav::close()
{
	this->file.close();
}

void Wav::open(const char *fileName)
{
	if (this->file.open(fileName, File::BINARY_READ) == false)
	{
		throw Exception(TRACE,
			std::string("Can not open wav: ") + fileName);
	}

	char header[Wav::HEADER_SIZE];
	int readSize = this->file.read(header, Wav::HEADER_SIZE);

	if (readSize == Wav::HEADER_SIZE &&
		compareQuadBytes("RIFF", &header[0]) &&
		compareQuadBytes("WAVE", &header[8]) &&
		compareQuadBytes("fmt ", &header[12]))
	{
		uint32_t chunkSize = Convert::combineQuadBytes(
			header[4], header[5], header[6], header[7]);
		uint32_t subChunk1Size = Convert::combineQuadBytes(
			header[16], header[17], header[18], header[19]);
		uint32_t subChunk2Size = Convert::combineQuadBytes(
			header[40], header[41], header[42], header[43]);

		if (4 + (8 + subChunk1Size) + (8 + subChunk2Size) != chunkSize)
			throw Exception(TRACE, "Wav chunk size error.");

		this->info.channel = Convert::combineDualBytes(
			header[22], header[23]);
		this->info.sampleRate = Convert::combineQuadBytes(
			header[24], header[25], header[26], header[27]);
		this->info.averageBytesPerSecond = Convert::combineQuadBytes(
			header[28], header[29], header[30], header[31]);
		this->info.blockAlign = Convert::combineDualBytes(
			header[32], header[33]);;
		this->info.bitsPerSample = Convert::combineDualBytes(
			header[34], header[35]);
		this->info.dataByteSize = subChunk2Size;
	}
	else
	{
		throw Exception(TRACE, "Wav header error.");
	}
}

uint32_t Wav::getSamples() const
{
	const uint32_t blockAlign = this->info.blockAlign;
	const uint32_t bytesPreSample = this->info.bitsPerSample / 8;
	uint32_t totalBlock = this->info.dataByteSize /
		(this->info.channel * blockAlign * bytesPreSample);

	return totalBlock * blockAlign;
}

uint32_t Wav::readAll(Wav::Raw &buffer)
{
	uint32_t dataSize = this->getSize();

	this->file.goToBegin(Wav::HEADER_SIZE);
	buffer.resize(dataSize);

	return (uint32_t)this->file.read(&buffer[0], (File::SizeType)dataSize);
}

Wav::Raw Wav::extractChannel(const Wav::Raw &wavBuffer,
	uint16_t channelIndex)
{
	if (this->info.channel == 1)
		return wavBuffer;

	if (channelIndex > this->info.channel)
		throw Exception(TRACE, "Channel does not exist.");

	const uint32_t bytesPreSample = this->info.bitsPerSample / 8;
	const uint32_t blockAlign = this->info.blockAlign;
	const uint32_t channelBlockSize = blockAlign * bytesPreSample;
	const uint32_t blockSize = channelBlockSize * this->info.channel;
	const uint32_t totalBlock = this->info.dataByteSize / blockSize;
	const uint32_t channelSize = this->info.dataByteSize / this->info.channel;
	const uint32_t channelSamples = channelSize / bytesPreSample;

	Raw channelBuffer;

	channelBuffer.resize(totalBlock * blockAlign * bytesPreSample);

	const char *block = wavBuffer.data() + blockAlign * channelIndex;
	char *out = &channelBuffer[0];

	// unroll loop
	if (bytesPreSample == 2)
	{
		for (uint32_t i = 0; i < channelSamples; ++i)
		{
			out[0] = block[0];
			out[1] = block[1];
			out += 2;
			block += blockAlign;
		}
	}
	else if (bytesPreSample == 1)
	{
		for (uint32_t i = 0; i < channelSamples; ++i)
		{
			out[0] = block[0];
			out += 1;
			block += blockAlign;
		}
	}
	else
	{
		for (uint32_t i = 0; i < channelSamples; ++i)
		{
			::memcpy(out, block, bytesPreSample);
			out += bytesPreSample;
			block += blockAlign;
		}
	}

	return channelBuffer;
}

void Wav::save(const char *fileName, const Wav::Channels &channels)
{
	if (channels.size() == 0)
		return;

	if (this->info.channel != channels.size())
	{
		this->info.channel = (uint16_t)channels.size();
		this->info.dataByteSize = this->info.channel * channels[0].size();
		this->info.averageBytesPerSecond =
			Wav::getAverageBytesPerSecond(this->info);
	}

	this->file.open(fileName, File::BINARY_WRITE);
	this->writeHeader();
	this->writeChannels(channels);
}

bool Wav::compareQuadBytes(const char *quad, const char *compared)
{
	return compared[0] == quad[0] && compared[1] == quad[1] &&
		compared[2] == quad[2] && compared[3] == quad[3];
}

void Wav::writeQuadBytes(const char *quad, char *out)
{
	out[0] = quad[0];
	out[1] = quad[1];
	out[2] = quad[2];
	out[3] = quad[3];
}

void Wav::writeHeader()
{
	char header[Wav::HEADER_SIZE];
	const uint16_t subChunk1Size = 16;
	const uint32_t chunkSize = 4 + (8 + subChunk1Size) +
		(8 + this->info.dataByteSize);

	writeQuadBytes("RIFF", &header[0]);
	Convert::splitQuadBytes(chunkSize, &header[4]);
	writeQuadBytes("WAVE", &header[8]);
	writeQuadBytes("fmt ", &header[12]);
	Convert::splitQuadBytes(subChunk1Size, &header[16]);
	Convert::splitDualBytes(0x01, &header[20]);
	Convert::splitDualBytes(this->info.channel, &header[22]);
	Convert::splitQuadBytes(this->info.sampleRate, &header[24]);
	Convert::splitQuadBytes(this->info.averageBytesPerSecond, &header[28]);
	Convert::splitDualBytes(this->info.blockAlign, &header[32]);
	Convert::splitDualBytes(this->info.bitsPerSample, &header[34]);
	writeQuadBytes("data", &header[36]);
	Convert::splitQuadBytes(this->info.dataByteSize, &header[40]);

	this->file.write(header, Wav::HEADER_SIZE);
}

void Wav::writeChannels(const Wav::Channels &channels)
{
	if (channels.size() == 0)
		return;

	const uint32_t bytesPreSample = this->info.bitsPerSample / 8;
	const uint32_t blockAlign = this->info.blockAlign;
	const uint32_t channelBlockSize = blockAlign * bytesPreSample;
	const uint32_t blockSize = channelBlockSize * this->info.channel;
	const uint32_t totalBlock = this->info.dataByteSize / blockSize;
	const uint32_t channelDataLength = channels[0].size();

	std::vector<const char *> channelPtr;
	channelPtr.reserve(channels.size());

	for (uint32_t i = 0; i < channels.size(); ++i)
	{
		channelPtr[i] = &channels[i][0];

		if (channels[i].size() != channelDataLength)
			throw Exception(TRACE, "Channel data size does not match.");
	}

	for (uint32_t i = 0; i < totalBlock; ++i)
	{
		for (uint32_t a = 0; a < blockAlign; ++a)
		{
			for (uint32_t c = 0; c < channels.size(); ++c)
			{
				this->file.write(channelPtr[c], (File::SizeType)bytesPreSample);
				channelPtr[c] += bytesPreSample;
			}
		}
	}
}
<commit_msg>Fix Wav bug.<commit_after>#include <cstring>

#include "Wav.hpp"
#include "common/Exception.hpp"
#include "common/Convert.hpp"
#include "common/Log.hpp"

Wav::Wav(const char *fileName)
{
	this->open(fileName);
}

Wav::~Wav()
{
	this->close();
}

void Wav::close()
{
	this->file.close();
}

void Wav::open(const char *fileName)
{
	if (this->file.open(fileName, File::BINARY_READ) == false)
	{
		throw Exception(TRACE,
			std::string("Can not open wav: ") + fileName);
	}

	char header[Wav::HEADER_SIZE];
	int readSize = this->file.read(header, Wav::HEADER_SIZE);

	if (readSize == Wav::HEADER_SIZE &&
		compareQuadBytes("RIFF", &header[0]) &&
		compareQuadBytes("WAVE", &header[8]) &&
		compareQuadBytes("fmt ", &header[12]))
	{
		uint32_t chunkSize = Convert::combineQuadBytes(
			header[4], header[5], header[6], header[7]);
		uint32_t subChunk1Size = Convert::combineQuadBytes(
			header[16], header[17], header[18], header[19]);
		uint32_t subChunk2Size = Convert::combineQuadBytes(
			header[40], header[41], header[42], header[43]);

		if (4 + (8 + subChunk1Size) + (8 + subChunk2Size) != chunkSize)
			throw Exception(TRACE, "Wav chunk size error.");

		this->info.channel = Convert::combineDualBytes(
			header[22], header[23]);
		this->info.sampleRate = Convert::combineQuadBytes(
			header[24], header[25], header[26], header[27]);
		this->info.averageBytesPerSecond = Convert::combineQuadBytes(
			header[28], header[29], header[30], header[31]);
		this->info.blockAlign = Convert::combineDualBytes(
			header[32], header[33]);;
		this->info.bitsPerSample = Convert::combineDualBytes(
			header[34], header[35]);
		this->info.dataByteSize = subChunk2Size;
	}
	else
	{
		throw Exception(TRACE, "Wav header error.");
	}
}

uint32_t Wav::getSamples() const
{
	const uint32_t blockAlign = this->info.blockAlign;
	const uint32_t bytesPreSample = this->info.bitsPerSample / 8;
	uint32_t totalBlock = this->info.dataByteSize /
		(this->info.channel * blockAlign * bytesPreSample);

	return totalBlock * blockAlign;
}

uint32_t Wav::readAll(Wav::Raw &buffer)
{
	uint32_t dataSize = this->getSize();

	this->file.goToBegin(Wav::HEADER_SIZE);
	buffer.resize(dataSize);

	return (uint32_t)this->file.read(&buffer[0], (File::SizeType)dataSize);
}

Wav::Raw Wav::extractChannel(const Wav::Raw &wavBuffer,
	uint16_t channelIndex)
{
	if (this->info.channel == 1)
		return wavBuffer;

	if (channelIndex > this->info.channel)
		throw Exception(TRACE, "Channel does not exist.");

	const uint32_t bytesPreSample = this->info.bitsPerSample / 8;
	const uint32_t blockAlign = this->info.blockAlign;
	const uint32_t channelBlockSize = blockAlign * bytesPreSample;
	const uint32_t blockSize = channelBlockSize * this->info.channel;
	const uint32_t totalBlock = this->info.dataByteSize / blockSize;
	const uint32_t channelSize = this->info.dataByteSize / this->info.channel;
	const uint32_t channelSamples = channelSize / bytesPreSample;

	Raw channelBuffer;

	channelBuffer.resize(totalBlock * blockAlign * bytesPreSample);

	const char *block = wavBuffer.data() + bytesPreSample * channelIndex;
	char *out = &channelBuffer[0];

	// unroll loop
	if (bytesPreSample == 2)
	{
		for (uint32_t i = 0; i < channelSamples; ++i)
		{
			out[0] = block[0];
			out[1] = block[1];
			out += 2;
			block += blockAlign;
		}
	}
	else if (bytesPreSample == 1)
	{
		for (uint32_t i = 0; i < channelSamples; ++i)
		{
			out[0] = block[0];
			out += 1;
			block += blockAlign;
		}
	}
	else
	{
		for (uint32_t i = 0; i < channelSamples; ++i)
		{
			::memcpy(out, block, bytesPreSample);
			out += bytesPreSample;
			block += blockAlign;
		}
	}

	return channelBuffer;
}

void Wav::save(const char *fileName, const Wav::Channels &channels)
{
	if (channels.size() == 0)
		return;

	if (this->info.channel != channels.size())
	{
		this->info.channel = (uint16_t)channels.size();
		this->info.dataByteSize = this->info.channel * channels[0].size();
		this->info.averageBytesPerSecond =
			Wav::getAverageBytesPerSecond(this->info);
	}

	this->file.open(fileName, File::BINARY_WRITE);
	this->writeHeader();
	this->writeChannels(channels);
}

bool Wav::compareQuadBytes(const char *quad, const char *compared)
{
	return compared[0] == quad[0] && compared[1] == quad[1] &&
		compared[2] == quad[2] && compared[3] == quad[3];
}

void Wav::writeQuadBytes(const char *quad, char *out)
{
	out[0] = quad[0];
	out[1] = quad[1];
	out[2] = quad[2];
	out[3] = quad[3];
}

void Wav::writeHeader()
{
	char header[Wav::HEADER_SIZE];
	const uint16_t subChunk1Size = 16;
	const uint32_t chunkSize = 4 + (8 + subChunk1Size) +
		(8 + this->info.dataByteSize);

	writeQuadBytes("RIFF", &header[0]);
	Convert::splitQuadBytes(chunkSize, &header[4]);
	writeQuadBytes("WAVE", &header[8]);
	writeQuadBytes("fmt ", &header[12]);
	Convert::splitQuadBytes(subChunk1Size, &header[16]);
	Convert::splitDualBytes(0x01, &header[20]);
	Convert::splitDualBytes(this->info.channel, &header[22]);
	Convert::splitQuadBytes(this->info.sampleRate, &header[24]);
	Convert::splitQuadBytes(this->info.averageBytesPerSecond, &header[28]);
	Convert::splitDualBytes(this->info.blockAlign, &header[32]);
	Convert::splitDualBytes(this->info.bitsPerSample, &header[34]);
	writeQuadBytes("data", &header[36]);
	Convert::splitQuadBytes(this->info.dataByteSize, &header[40]);

	this->file.write(header, Wav::HEADER_SIZE);
}

void Wav::writeChannels(const Wav::Channels &channels)
{
	if (channels.size() == 0)
		return;

	const uint32_t bytesPreSample = this->info.bitsPerSample / 8;
	const uint32_t blockAlign = this->info.blockAlign;
	const uint32_t channelBlockSize = blockAlign * bytesPreSample;
	const uint32_t blockSize = channelBlockSize * this->info.channel;
	const uint32_t totalBlock = this->info.dataByteSize / blockSize;
	const uint32_t channelDataLength = channels[0].size();

	std::vector<const char *> channelPtr;
	channelPtr.reserve(channels.size());

	for (uint32_t i = 0; i < channels.size(); ++i)
	{
		channelPtr[i] = &channels[i][0];

		if (channels[i].size() != channelDataLength)
			throw Exception(TRACE, "Channel data size does not match.");
	}

	for (uint32_t i = 0; i < totalBlock; ++i)
	{
		for (uint32_t a = 0; a < blockAlign; ++a)
		{
			for (uint32_t c = 0; c < channels.size(); ++c)
			{
				this->file.write(channelPtr[c], (File::SizeType)bytesPreSample);
				channelPtr[c] += bytesPreSample;
			}
		}
	}
}
<|endoftext|>


<commit_before>#ifndef __COMPUTE_TASK_HPP_INCLUDED
#define __COMPUTE_TASK_HPP_INCLUDED

#include "entity.hpp"
#include "compute_task_struct.hpp"
#include "pre_iterate_callback.hpp"
#include "post_iterate_callback.hpp"
#include "family_templates.hpp"
#include "code/ylikuutio/opengl/opengl.hpp"
#include "code/ylikuutio/hierarchy/hierarchy_templates.hpp"

// Include GLEW
#include "code/ylikuutio/opengl/ylikuutio_glew.hpp" // GLfloat, GLuint etc.

// Include standard headers
#include <cstddef>  // std::size_t
#include <iostream> // std::cout, std::cin, std::cerr
#include <memory>   // std::make_shared, std::shared_ptr
#include <queue>    // std::queue
#include <stdint.h> // uint32_t etc.
#include <vector>   // std::vector

// `yli::ontology::ComputeTask` is a class which contains the data for a single
// computing task. `ComputeTask` does not have the OpenGL shaders used to process
// the data. Instead, the shaders are contained by the parent `Entity` which is
// an `yli::ontology::ComputeTask` instance.
//
// For example, `yli::ontology::Shader` can have vertex and fragment shaders for
// computing the distances between nodes of a graph. Then, each `ComputeTask`
// would contain the graph data, eg. as a distance matrix. Then, rendering a
// `ComputeTask` means computing that task.
//
// Rendering a `ComputeTask` is done by iterating the task until either
// `end_condition_callback_engine->execute()` returns `true`, or until
// `n_max_iterations` is reached. If `end_condition_callback_engine` is `nullptr`
// or `end_condition_callback_engine->execute()` does not not return an `AnyValue`
// which contains `datatypes::BOOL`, then `end_condition_callback_engine` is ignored
// and `n_max_iterations` is the exact number of iterations to be done. However,
// even if `end_condition_callback_engine->execute()` would return an invalid return
// value, that is, not an `AnyValue` which contains `datatypes::BOOL`,
// `end_condition_callback_engine->execute()` is still called and taken into account
// in every iteration.
//
// When iterating, there is a `PreIterateCallback` which is executed before each iteration,
// and also a `PostIterateCallback` which is executed correspondingly after each iteration.
// Of course `PreRenderCallback` and `PostRenderCallback` can be used as well.
// `PreRenderCallback` gets executed before the first `PreIterateCallback` call, and
// `PostRenderCallback` gets executed after the last `PostRenderCallback` call.
// All these callbacks are optional and can be left to `nullptr` if they are not needed.

namespace yli
{
    namespace callback_system
    {
        class CallbackEngine;
    }

    namespace ontology
    {
        class Shader;

        class ComputeTask: public yli::ontology::Entity
        {
            public:
                ComputeTask(yli::ontology::Universe* const universe, const ComputeTaskStruct& compute_task_struct)
                    : Entity(universe)
                {
                    // constructor.
                    this->parent = compute_task_struct.parent;
                    this->end_condition_callback_engine = compute_task_struct.end_condition_callback_engine;
                    this->n_max_iterations = compute_task_struct.n_max_iterations;
                    this->compute_taskID = compute_task_struct.compute_taskID;
                    this->framebuffer = 0;
                    this->texture = 0;
                    this->render_buffer = 0;

                    this->texture_width = compute_task_struct.texture_width;
                    this->texture_height = compute_task_struct.texture_height;
                    this->preiterate_callback = compute_task_struct.preiterate_callback;
                    this->postiterate_callback = compute_task_struct.postiterate_callback;

                    // Create FBO (off-screen framebuffer object).
                    glGenFramebuffers(1, &this->framebuffer);

                    // Bind offscreen buffer.
                    glBindFramebuffer(GL_FRAMEBUFFER, this->framebuffer);

                    // Create texture.
                    glGenTextures(1, &this->texture);
                    glBindTexture(GL_TEXTURE_2D, this->texture);

                    // Define texture.
                    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, this->texture_width, this->texture_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);

                    yli::opengl::set_filtering_parameters();

                    // Attach texture.
                    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->texture, 0);

                    // Create and bind render buffer with depth and stencil attachments.
                    glGenRenderbuffers(1, &this->render_buffer);
                    glBindRenderbuffer(GL_RENDERBUFFER, this->render_buffer);
                    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, this->texture_width, this->texture_height);
                    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, this->render_buffer);

                    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
                    {
                        std::cerr << "ERROR: `ComputeTask::ComputeTask`: framebuffer is not complete!\n";
                    }

                    // Get `childID` from `Shader` and set pointer to this `ComputeTask`.
                    this->bind_to_parent();

                    // `yli::ontology::Entity` member variables begin here.
                    this->type_string = "yli::ontology::ComputeTask*";
                    this->can_be_erased = true;
                }

                // destructor.
                ~ComputeTask();

                yli::ontology::Entity* get_parent() const override;

                template<class T1>
                    friend void yli::hierarchy::bind_child_to_parent(T1 child_pointer, std::vector<T1>& child_pointer_vector, std::queue<std::size_t>& free_childID_queue, std::size_t& number_of_children);
                template<class T1>
                    friend std::size_t yli::ontology::get_number_of_descendants(const std::vector<T1>& child_pointer_vector);

            private:
                void bind_to_parent();

                // This method renders this `ComputeTask`, that is, computes this task.
                void render();

                void preiterate() const;
                void postiterate() const;

                std::size_t get_number_of_children() const override;
                std::size_t get_number_of_descendants() const override;

                yli::ontology::Shader* parent; // pointer to the `Shader`.

                // End iterating when `end_condition_callback_engine` returns `true`.
                std::shared_ptr<yli::callback_system::CallbackEngine> end_condition_callback_engine;

                // This is the maximum number of iterations.
                // If `end_condition_callback_engine` is `nullptr`, then this is the number of iterations.
                // If `end_condition_callback_engine` is not `nullptr`, then this is the maximum number of iterations.
                std::size_t n_max_iterations;

                std::size_t compute_taskID;

                uint32_t framebuffer;
                uint32_t texture;
                uint32_t render_buffer;

                std::size_t texture_width;
                std::size_t texture_height;

                PreIterateCallback preiterate_callback;
                PostIterateCallback postiterate_callback;
        };
    }
}

#endif
<commit_msg>`ComputeTask` constructor: reordered code lines.<commit_after>#ifndef __COMPUTE_TASK_HPP_INCLUDED
#define __COMPUTE_TASK_HPP_INCLUDED

#include "entity.hpp"
#include "compute_task_struct.hpp"
#include "pre_iterate_callback.hpp"
#include "post_iterate_callback.hpp"
#include "family_templates.hpp"
#include "code/ylikuutio/opengl/opengl.hpp"
#include "code/ylikuutio/hierarchy/hierarchy_templates.hpp"

// Include GLEW
#include "code/ylikuutio/opengl/ylikuutio_glew.hpp" // GLfloat, GLuint etc.

// Include standard headers
#include <cstddef>  // std::size_t
#include <iostream> // std::cout, std::cin, std::cerr
#include <memory>   // std::make_shared, std::shared_ptr
#include <queue>    // std::queue
#include <stdint.h> // uint32_t etc.
#include <vector>   // std::vector

// `yli::ontology::ComputeTask` is a class which contains the data for a single
// computing task. `ComputeTask` does not have the OpenGL shaders used to process
// the data. Instead, the shaders are contained by the parent `Entity` which is
// an `yli::ontology::ComputeTask` instance.
//
// For example, `yli::ontology::Shader` can have vertex and fragment shaders for
// computing the distances between nodes of a graph. Then, each `ComputeTask`
// would contain the graph data, eg. as a distance matrix. Then, rendering a
// `ComputeTask` means computing that task.
//
// Rendering a `ComputeTask` is done by iterating the task until either
// `end_condition_callback_engine->execute()` returns `true`, or until
// `n_max_iterations` is reached. If `end_condition_callback_engine` is `nullptr`
// or `end_condition_callback_engine->execute()` does not not return an `AnyValue`
// which contains `datatypes::BOOL`, then `end_condition_callback_engine` is ignored
// and `n_max_iterations` is the exact number of iterations to be done. However,
// even if `end_condition_callback_engine->execute()` would return an invalid return
// value, that is, not an `AnyValue` which contains `datatypes::BOOL`,
// `end_condition_callback_engine->execute()` is still called and taken into account
// in every iteration.
//
// When iterating, there is a `PreIterateCallback` which is executed before each iteration,
// and also a `PostIterateCallback` which is executed correspondingly after each iteration.
// Of course `PreRenderCallback` and `PostRenderCallback` can be used as well.
// `PreRenderCallback` gets executed before the first `PreIterateCallback` call, and
// `PostRenderCallback` gets executed after the last `PostRenderCallback` call.
// All these callbacks are optional and can be left to `nullptr` if they are not needed.

namespace yli
{
    namespace callback_system
    {
        class CallbackEngine;
    }

    namespace ontology
    {
        class Shader;

        class ComputeTask: public yli::ontology::Entity
        {
            public:
                ComputeTask(yli::ontology::Universe* const universe, const ComputeTaskStruct& compute_task_struct)
                    : Entity(universe)
                {
                    // constructor.
                    this->parent = compute_task_struct.parent;
                    this->end_condition_callback_engine = compute_task_struct.end_condition_callback_engine;
                    this->n_max_iterations = compute_task_struct.n_max_iterations;
                    this->compute_taskID = compute_task_struct.compute_taskID;
                    this->framebuffer = 0;
                    this->texture = 0;
                    this->render_buffer = 0;

                    this->texture_width = compute_task_struct.texture_width;
                    this->texture_height = compute_task_struct.texture_height;
                    this->preiterate_callback = compute_task_struct.preiterate_callback;
                    this->postiterate_callback = compute_task_struct.postiterate_callback;

                    // Get `childID` from `Shader` and set pointer to this `ComputeTask`.
                    this->bind_to_parent();

                    // Create FBO (off-screen framebuffer object).
                    glGenFramebuffers(1, &this->framebuffer);

                    // Bind offscreen buffer.
                    glBindFramebuffer(GL_FRAMEBUFFER, this->framebuffer);

                    // Create texture.
                    glGenTextures(1, &this->texture);
                    glBindTexture(GL_TEXTURE_2D, this->texture);

                    // Define texture.
                    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, this->texture_width, this->texture_height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);

                    yli::opengl::set_filtering_parameters();

                    // Attach texture.
                    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, this->texture, 0);

                    // Create and bind render buffer with depth and stencil attachments.
                    glGenRenderbuffers(1, &this->render_buffer);
                    glBindRenderbuffer(GL_RENDERBUFFER, this->render_buffer);
                    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, this->texture_width, this->texture_height);
                    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, this->render_buffer);

                    if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
                    {
                        std::cerr << "ERROR: `ComputeTask::ComputeTask`: framebuffer is not complete!\n";
                    }

                    // `yli::ontology::Entity` member variables begin here.
                    this->type_string = "yli::ontology::ComputeTask*";
                    this->can_be_erased = true;
                }

                // destructor.
                ~ComputeTask();

                yli::ontology::Entity* get_parent() const override;

                template<class T1>
                    friend void yli::hierarchy::bind_child_to_parent(T1 child_pointer, std::vector<T1>& child_pointer_vector, std::queue<std::size_t>& free_childID_queue, std::size_t& number_of_children);
                template<class T1>
                    friend std::size_t yli::ontology::get_number_of_descendants(const std::vector<T1>& child_pointer_vector);

            private:
                void bind_to_parent();

                // This method renders this `ComputeTask`, that is, computes this task.
                void render();

                void preiterate() const;
                void postiterate() const;

                std::size_t get_number_of_children() const override;
                std::size_t get_number_of_descendants() const override;

                yli::ontology::Shader* parent; // pointer to the `Shader`.

                // End iterating when `end_condition_callback_engine` returns `true`.
                std::shared_ptr<yli::callback_system::CallbackEngine> end_condition_callback_engine;

                // This is the maximum number of iterations.
                // If `end_condition_callback_engine` is `nullptr`, then this is the number of iterations.
                // If `end_condition_callback_engine` is not `nullptr`, then this is the maximum number of iterations.
                std::size_t n_max_iterations;

                std::size_t compute_taskID;

                uint32_t framebuffer;
                uint32_t texture;
                uint32_t render_buffer;

                std::size_t texture_width;
                std::size_t texture_height;

                PreIterateCallback preiterate_callback;
                PostIterateCallback postiterate_callback;
        };
    }
}

#endif
<|endoftext|>