<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_build_smp.H $      */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file p9_build_smp.H
/// @brief Perform fabric configuration (FAPI2)
///
/// Perform fabric SMP build/reconfiguration operations.
///
/// Platform Notes:
///     This HWP has multiple IPL use cases.  In all all cases the HWP input
///     is expected to contain an entry for each chip within the scope of
///     the new SMP to be constructed (with valid attribute state repesenting all
///     active links that are fully contained within the new SMP).
///
///     The p9_build_smp_operation HWP input defines the desired
///     reconfiguration option to be performed:
///
///         SMP_ACTIVATE_PHASE1 (HBI):
///             o init epsilon registers,
///             o program FBC configuration dependent registers (switch C/D)
///             o join all single chip 'island' fabrics into drawer level
///               SMP (switch A/B)
///
///         SMP_ACTIVATE_PHASE2 (FSP):
///             o join collection of drawer level SMPs into full system SMP
///               (switch A/B)
///
/// @author Joe McGill <jmcgill@us.ibm.com>
/// @author Christy Graves <clgraves@us.ibm.com>
///

//
// *HWP HWP Owner: Joe McGill <jmcgill@us.ibm.com>
// *HWP FW Owner: Thi Tran <thi@us.ibm.com>
// *HWP Team: Nest
// *HWP Level: 1
// *HWP Consumed by: HB,FSP
//

#ifndef _P9_BUILD_SMP_H_
#define _P9_BUILD_SMP_H_

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include <fapi2.H>

//------------------------------------------------------------------------------
// Structure definitions
//------------------------------------------------------------------------------

// HWP argument, define supported execution modes
enum p9_build_smp_operation
{
    // call from HB (init epsilons, switch C/D + A/B)
    // used to initialize scope of HBI drawer
    SMP_ACTIVATE_PHASE1 = 1,
    // call from FSP (only switch A/B)
    // used to stitch drawers/CCM
    SMP_ACTIVATE_PHASE2 = 2
};

// HWP argument structure defining properties of this chip
struct p9_build_smp_proc_chip
{
    // target for this chip
    fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> this_chip;
    // set if this chip should be designated fabric
    // master post-reconfiguration
    // NOTE: this chip must currently be designated a
    //       master in its enclosing fabric
    //       PHASE1/HB: any chip
    //       PHASE2/FSP: any current drawer master
    bool is_master_chip_sys_next;
};

/// function pointer typedef definition for HWP call support
typedef fapi2::ReturnCode (*p9_build_smp_FP_t) (std::vector<p9_build_smp_proc_chip>&,
        const p9_build_smp_operation);

//------------------------------------------------------------------------------
// Function prototypes
//------------------------------------------------------------------------------

extern "C"
{

///
/// @brief Perform fabric SMP reconfiguration operation
///
/// @param[in] i_proc_chips Vector of structures defining properties of each chip
/// @param[op] i_op Enumerated type representing SMP build phase (HB or FSP)
/// @return fapi::ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
    fapi2::ReturnCode p9_build_smp(std::vector<p9_build_smp_proc_chip>& i_proc_chips,
                                   const p9_build_smp_operation i_op);

} // extern "C"

#endif // _P9_BUILD_SMP_H_
<commit_msg>L2 - p9_build_smp HWPs<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/nest/p9_build_smp.H $      */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2019                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* Licensed under the Apache License, Version 2.0 (the "License");        */
/* you may not use this file except in compliance with the License.       */
/* You may obtain a copy of the License at                                */
/*                                                                        */
/*     http://www.apache.org/licenses/LICENSE-2.0                         */
/*                                                                        */
/* Unless required by applicable law or agreed to in writing, software    */
/* distributed under the License is distributed on an "AS IS" BASIS,      */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or        */
/* implied. See the License for the specific language governing           */
/* permissions and limitations under the License.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
///
/// @file p9_build_smp.H
/// @brief Perform fabric configuration (FAPI2)
///
/// Perform fabric SMP build/reconfiguration operations.
///
/// Platform Notes:
///     This HWP has multiple IPL use cases.  In all all cases the HWP input
///     is expected to contain an entry for each chip within the scope of
///     the new SMP to be constructed (with valid attribute state repesenting all
///     active links that are fully contained within the new SMP).
///
///     The p9_build_smp_operation HWP input defines the desired
///     reconfiguration option to be performed:
///
///         SMP_ACTIVATE_PHASE1 (HBI):
///             o init epsilon registers,
///             o program FBC configuration dependent registers (switch C/D)
///             o join all single chip 'island' fabrics into drawer level
///               SMP (switch A/B)
///
///         SMP_ACTIVATE_PHASE2 (FSP):
///             o join collection of drawer level SMPs into full system SMP
///               (switch A/B)
///
/// *HWP HWP Owner: Joe McGill <jmcgill@us.ibm.com>
/// *HWP FW Owner: Thi Tran <thi@us.ibm.com>
/// *HWP Team: Nest
/// *HWP Level: 2
/// *HWP Consumed by: HB,FSP
///

#ifndef _P9_BUILD_SMP_H_
#define _P9_BUILD_SMP_H_

//------------------------------------------------------------------------------
// Includes
//------------------------------------------------------------------------------
#include <fapi2.H>
#include <map>
#include <p9_fab_smp_utils.H>

//------------------------------------------------------------------------------
// Constant definitions
//------------------------------------------------------------------------------
// PB shadow register constant definition
const uint8_t P9_BUILD_SMP_NUM_SHADOWS = 3;

// HWP argument, define supported execution modes
enum p9_build_smp_operation
{
    // Call from HB (init epsilons, switch C/D + A/B),
    // used to initialize scope of HBI drawer
    SMP_ACTIVATE_PHASE1 = 1,
    // Call from FSP (only switch A/B), used to stitch drawers/CCM
    SMP_ACTIVATE_PHASE2 = 2
};

// Core/nest frequency ratio cutpoints (epsilon)
enum p9_build_smp_core_ratio
{
    P9_BUILD_SMP_CORE_RATIO_8_8 = 0,
    P9_BUILD_SMP_CORE_RATIO_7_8 = 1,
    P9_BUILD_SMP_CORE_RATIO_6_8 = 2,
    P9_BUILD_SMP_CORE_RATIO_5_8 = 3,
    P9_BUILD_SMP_CORE_RATIO_4_8 = 4,
    P9_BUILD_SMP_CORE_RATIO_2_8 = 5
};

// Core floor/nest frequency ratio cutpoints (CPU delay)
enum p9_build_smp_cpu_delay
{
    P9_BUILD_SMP_CPU_DELAY_4800_2400 = 0,
    P9_BUILD_SMP_CPU_DELAY_4431_2400 = 1,
    P9_BUILD_SMP_CPU_DELAY_4114_2400 = 2,
    P9_BUILD_SMP_CPU_DELAY_3840_2400 = 3,
    P9_BUILD_SMP_CPU_DELAY_3600_2400 = 4,
    P9_BUILD_SMP_CPU_DELAY_3338_2400 = 5,
    P9_BUILD_SMP_CPU_DELAY_3200_2400 = 6,
    P9_BUILD_SMP_CPU_DELAY_3032_2400 = 7,
    P9_BUILD_SMP_CPU_DELAY_2880_2400 = 8,
    P9_BUILD_SMP_CPU_DELAY_2743_2400 = 9,
    P9_BUILD_SMP_CPU_DELAY_2618_2400 = 10,
    P9_BUILD_SMP_CPU_DELAY_2504_2400 = 11,
    P9_BUILD_SMP_CPU_DELAY_2400_2400 = 12
};

//------------------------------------------------------------------------------
// Structure definitions
//------------------------------------------------------------------------------

// HWP argument structure defining properties of this chip
// and links which should be considered
struct p9_build_smp_proc_chip
{
    // Target for this chip
    fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP> this_chip;

    // Set if this chip should be designated fabric
    // master post-reconfiguration
    // NOTE: this chip must currently be designated a
    //       master in its enclosing fabric
    //       PHASE1/HB: any chip
    //       PHASE2/FSP: any current drawer master
    bool master_chip_sys_next;

    // XBUS chiplet targets connected to X links
    fapi2::Target<fapi2::TARGET_TYPE_XBUS> x0_chip;
    fapi2::Target<fapi2::TARGET_TYPE_XBUS> x1_chip;
    fapi2::Target<fapi2::TARGET_TYPE_XBUS> x2_chip;

    // Obus chiplet targets, connected to either A or X links
    fapi2::Target<fapi2::TARGET_TYPE_OBUS> o0_chip;
    fapi2::Target<fapi2::TARGET_TYPE_OBUS> o1_chip;
    fapi2::Target<fapi2::TARGET_TYPE_OBUS> o2_chip;
    fapi2::Target<fapi2::TARGET_TYPE_OBUS> o3_chip;

};

// Structure to encapsulate system epsilon configuration

const uint8_t NUMBER_OF_EPSILON_READ_TIERS = 3;
const uint8_t NUMBER_OF_EPSILON_WRITE_TIERS = 3;

struct p9_build_smp_eps_cfg
{
    // Epsilon configuration inputs
    int8_t gb_percentage;
    p9_fab_smp_eps_table_type table_type;

    // Epsilon protection count
    // read, tier0 (LN)
    // read, tier1 (NN/G)
    // read, tier2 (RN/VG)
    // write, tier1 (LN/NN/G)
    // write, tier2 (RN/VG)
    uint32_t r_t[NUMBER_OF_EPSILON_READ_TIERS];  // Read, index is tier
    uint32_t w_t[NUMBER_OF_EPSILON_WRITE_TIERS]; // Write, index is tier
};

// Structure to represent fabric connectivty & properites for a single chip
// in the SMP topology
struct p9_build_smp_chip
{
    // associated HWP input structure
    p9_build_smp_proc_chip* chip;

    // Fabric chip/node ID
    p9_fab_smp_chip_id chip_id;
    p9_fab_smp_node_id node_id;

    // Optic mode (A or X)
    uint8_t smpOpticsMode;

    // TODO: RTC 147511 - Need to set enabled based on ATTR_PG attributes.
    // This is to prevent issuing SCOMs to a region that might be deconfigured,
    // and we can't use the state of a unit target (XBUS/OBUS) to make the
    // determination.
    bool nv_enabled = false;
    bool x_enabled = true;
    bool o_enabled = true;

    // Node/system master designation (curr)
    bool master_chip_node_curr;
    bool master_chip_sys_curr;

    // Node/system master designation (next)
    bool master_chip_node_next;
    bool issue_quiesce_next;
    bool quiesced_next;

};

// Structure to represent properties for a single node in the SMP topology
struct p9_build_smp_node
{
    // Chips which reside in this node
    std::map<p9_fab_smp_chip_id, p9_build_smp_chip> chips;

    // Node properties/attributes:
    // fabric node ID
    p9_fab_smp_node_id node_id;
};

// Structure to represent collection of nodes in SMP topology
struct p9_build_smp_system
{
    // nodes which reside in this SMP
    std::map<p9_fab_smp_node_id, p9_build_smp_node> nodes;

    // current system master for the purpose of launching
    // fabric reconfiguration operations
    bool master_chip_curr_set;
    p9_fab_smp_node_id master_chip_curr_node_id;
    p9_fab_smp_chip_id master_chip_curr_chip_id;

    // Indicate if optic is configured as A or X
    uint8_t smpOpticsMode;

    // System properties/attributes:
    // system frequencies (MHz):
    uint32_t freq_pb;
    uint32_t freq_a;
    uint32_t freq_x;
    uint32_t freq_core_floor;
    uint32_t freq_core_nom;
    uint32_t freq_core_ceiling;
    uint32_t freq_pcie;

    // Core/pb frequency ratios
    p9_build_smp_core_ratio core_floor_ratio;
    p9_build_smp_core_ratio core_ceiling_ratio;

    // CPU delay/RCMD highwater settings
    p9_build_smp_cpu_delay nom_cpu_delay;
    p9_build_smp_cpu_delay full_cpu_delay;

    // Fabric pump mode
    p9_fab_smp_pump_mode pump_mode;

    // System epsilon configuration
    p9_build_smp_eps_cfg eps_cfg;
};

/// function pointer typedef definition for HWP call support
typedef fapi2::ReturnCode (*p9_build_smp_FP_t)
(std::vector<p9_build_smp_proc_chip>&,
 const p9_build_smp_operation);

//------------------------------------------------------------------------------
// Function prototypes
//------------------------------------------------------------------------------

extern "C"
{

///
/// @brief Perform fabric SMP reconfiguration operation
///
/// @param[in] i_proc_chips Vector of structures defining properties of each chip
/// @param[op] i_op Enumerated type representing SMP build phase (HB or FSP)
///
/// @return fapi2:ReturnCode. FAPI2_RC_SUCCESS if success, else error code.
///
    fapi2::ReturnCode p9_build_smp(std::vector<p9_build_smp_proc_chip>& i_proc_chips,
                                   const p9_build_smp_operation i_op);

} // extern "C"

#endif // _P9_BUILD_SMP_H_
<|endoftext|>


<commit_before>/*
 * TinyJS
 *
 * A single-file Javascript-alike engine
 *
 * Authored By Gordon Williams <gw@pur3.co.uk>
 *
 * Copyright (C) 2009 Pur3 Ltd
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:

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

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

/*
 * This is a program to run all the tests in the tests folder...
 */

#include "utils.h"
#include "TinyJS.h"
#include "TinyJS_Functions.h"
#include "TinyJS_MathFunctions.h"
#include <assert.h>
#include <sys/stat.h>
#include <string>
#include <sstream>
#include <stdio.h>

#ifdef MTRACE
#include <mcheck.h>
#endif

//#define INSANE_MEMORY_DEBUG

#ifdef INSANE_MEMORY_DEBUG
// needs -rdynamic when compiling/linking
#include <execinfo.h>
#include <malloc.h>
#include <map>
#include <vector>
using namespace std;

void **get_stackframe()
{
    void **trace = (void**) malloc(sizeof (void*)*17);
    int trace_size = 0;

    for (int i = 0; i < 17; i++) trace[i] = (void*) 0;
    trace_size = backtrace(trace, 16);
    return trace;
}

void print_stackframe(char *header, void **trace)
{
    char **messages = (char **) NULL;
    int trace_size = 0;

    trace_size = 0;
    while (trace[trace_size]) trace_size++;
    messages = backtrace_symbols(trace, trace_size);

    printf("%s\n", header);
    for (int i = 0; i < trace_size; ++i)
    {
        printf("%s\n", messages[i]);
    }
    //free(messages);
}

/* Prototypes for our hooks.  */
static void *my_malloc_hook(size_t, const void *);
static void my_free_hook(void*, const void *);
static void *(*old_malloc_hook) (size_t, const void *);
static void (*old_free_hook) (void*, const void *);

map<void *, void **> malloced;

static void *my_malloc_hook(size_t size, const void *caller)
{
    /* Restore all old hooks */
    __malloc_hook = old_malloc_hook;
    __free_hook = old_free_hook;
    /* Call recursively */
    void *result = malloc(size);
    /* we call malloc here, so protect it too. */
    //printf ("malloc (%u) returns %p\n", (unsigned int) size, result);
    malloced[result] = get_stackframe();

    /* Restore our own hooks */
    __malloc_hook = my_malloc_hook;
    __free_hook = my_free_hook;
    return result;
}

static void my_free_hook(void *ptr, const void *caller)
{
    /* Restore all old hooks */
    __malloc_hook = old_malloc_hook;
    __free_hook = old_free_hook;
    /* Call recursively */
    free(ptr);
    /* we call malloc here, so protect it too. */
    //printf ("freed pointer %p\n", ptr);
    if (malloced.find(ptr) == malloced.end())
    {
        /*fprintf(stderr, "INVALID FREE\n");
        void *trace[16];
        int trace_size = 0;
        trace_size = backtrace(trace, 16);
        backtrace_symbols_fd(trace, trace_size, STDERR_FILENO);*/
    }
    else
        malloced.erase(ptr);
    /* Restore our own hooks */
    __malloc_hook = my_malloc_hook;
    __free_hook = my_free_hook;
}

void memtracing_init()
{
    old_malloc_hook = __malloc_hook;
    old_free_hook = __free_hook;
    __malloc_hook = my_malloc_hook;
    __free_hook = my_free_hook;
}

long gethash(void **trace)
{
    unsigned long hash = 0;
    while (*trace)
    {
        hash = (hash << 1) ^ (hash >> 63) ^ (unsigned long) *trace;
        trace++;
    }
    return hash;
}

void memtracing_kill()
{
    /* Restore all old hooks */
    __malloc_hook = old_malloc_hook;
    __free_hook = old_free_hook;

    map<long, void**> hashToReal;
    map<long, int> counts;
    map<void *, void **>::iterator it = malloced.begin();
    while (it != malloced.end())
    {
        long hash = gethash(it->second);
        hashToReal[hash] = it->second;

        if (counts.find(hash) == counts.end())
            counts[hash] = 1;
        else
            counts[hash]++;

        it++;
    }

    vector<pair<int, long> > sorting;
    map<long, int>::iterator countit = counts.begin();
    while (countit != counts.end())
    {
        sorting.push_back(pair<int, long>(countit->second, countit->first));
        countit++;
    }

    // sort
    bool done = false;
    while (!done)
    {
        done = true;
        for (int i = 0; i < sorting.size() - 1; i++)
        {
            if (sorting[i].first < sorting[i + 1].first)
            {
                pair<int, long> t = sorting[i];
                sorting[i] = sorting[i + 1];
                sorting[i + 1] = t;
                done = false;
            }
        }
    }

    for (int i = 0; i < sorting.size(); i++)
    {
        long hash = sorting[i].second;
        int count = sorting[i].first;
        char header[256];
        sprintf(header, "--------------------------- LEAKED %d", count);
        print_stackframe(header, hashToReal[hash]);
    }
}
#endif // INSANE_MEMORY_DEBUG

bool run_test(const char *filename)
{
    printf("TEST %s ", filename);
    struct stat results;
    if (!stat(filename, &results) == 0)
    {
        printf("Cannot stat file! '%s'\n", filename);
        return false;
    }
    int size = results.st_size;
    FILE *file = fopen(filename, "rb");
    /* if we open as text, the number of bytes read may be > the size we read */
    if (!file)
    {
        printf("Unable to open file! '%s'\n", filename);
        return false;
    }
    char *buffer = new char[size + 1];
    long actualRead = fread(buffer, 1, size, file);
    buffer[actualRead] = 0;
    buffer[size] = 0;
    fclose(file);

    CTinyJS s;
    registerFunctions(&s);
    registerMathFunctions(&s);
    s.setGlobal("result", jsInt(0));
    try
    {
        s.execute(buffer);
    }
    catch (const CScriptException &e)
    {
        printf("ERROR: %s\n", e.what());
    }
    bool pass = s.getGlobal("result")->toBoolean();

    if (pass)
        printf("PASS\n");
    else
    {
        char fn[64];
        sprintf(fn, "%s.fail.js", filename);
        FILE *f = fopen(fn, "wt");
        if (f)
        {
            std::string symbols = s.dumpJSONSymbols();
            fprintf(f, "%s", symbols.c_str());
            fclose(f);
        }

        printf("FAIL - symbols written to %s\n", fn);
    }

    delete[] buffer;
    return pass;
}

int main(int argc, char **argv)
{
#ifdef MTRACE
    mtrace();
#endif
#ifdef INSANE_MEMORY_DEBUG
    memtracing_init();
#endif
    printf("TinyJS test runner\n");
    printf("USAGE:\n");
    printf("   ./run_tests test.js       : run just one test\n");
    printf("   ./run_tests               : run all tests\n");
    if (argc == 2)
    {
        return !run_test(argv[1]);
    }

    int test_num = 1;
    int count = 0;
    int passed = 0;

    while (test_num < 1000)
    {
        char fn[32];
        sprintf(fn, "tests/test%03d.js", test_num);
        // check if the file exists - if not, assume we're at the end of our tests
        FILE *f = fopen(fn, "r");
        if (!f) break;
        fclose(f);

        if (run_test(fn))
            passed++;
        count++;
        test_num++;
    }

    printf("Done. %d tests, %d pass, %d fail\n", count, passed, count - passed);
#ifdef INSANE_MEMORY_DEBUG
    memtracing_kill();
#endif

#ifdef _DEBUG
#ifdef _WIN32
    _CrtDumpMemoryLeaks();
#endif
#endif
#ifdef MTRACE
    muntrace();
#endif

    return 0;
}
<commit_msg>Adaptation of 'run_tests.cpp' to the new code.<commit_after>/*
 * TinyJS
 *
 * A single-file Javascript-alike engine
 *
 * Authored By Gordon Williams <gw@pur3.co.uk>
 *
 * Copyright (C) 2009 Pur3 Ltd
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
 * of the Software, and to permit persons to whom the Software is furnished to do
 * so, subject to the following conditions:

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

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

/*
 * This is a program to run all the tests in the tests folder...
 */

#include "utils.h"
#include "TinyJS.h"
#include "TinyJS_Functions.h"
#include "TinyJS_MathFunctions.h"
#include <assert.h>
#include <sys/stat.h>
#include <string>
#include <sstream>
#include <stdio.h>

#ifdef MTRACE
#include <mcheck.h>
#endif

//#define INSANE_MEMORY_DEBUG

#ifdef INSANE_MEMORY_DEBUG
// needs -rdynamic when compiling/linking
#include <execinfo.h>
#include <malloc.h>
#include <map>
#include <vector>
using namespace std;

void **get_stackframe()
{
    void **trace = (void**) malloc(sizeof (void*)*17);
    int trace_size;

    for (int i = 0; i < 17; i++) trace[i] = (void*) 0;
    trace_size = backtrace(trace, 16);
    return trace;
}

void print_stackframe(char *header, void **trace)
{
    char **messages = (char **) NULL;
    int trace_size = 0;

    trace_size = 0;
    while (trace[trace_size]) trace_size++;
    messages = backtrace_symbols(trace, trace_size);

    printf("%s\n", header);
    for (int i = 0; i < trace_size; ++i)
    {
        printf("%s\n", messages[i]);
    }
    //free(messages);
}

/* Prototypes for our hooks.  */
static void *my_malloc_hook(size_t, const void *);
static void my_free_hook(void*, const void *);
static void *(*old_malloc_hook) (size_t, const void *);
static void (*old_free_hook) (void*, const void *);

map<void *, void **> malloced;

static void *my_malloc_hook(size_t size, const void *caller)
{
    /* Restore all old hooks */
    __malloc_hook = old_malloc_hook;
    __free_hook = old_free_hook;
    /* Call recursively */
    printf ("malloc (%u)... ", (unsigned int) size);
    void *result = malloc(size);
    /* we call malloc here, so protect it too. */
    printf ("returns %p\n", result);
    //malloced[result] = get_stackframe();

    /* Restore our own hooks */
    __malloc_hook = my_malloc_hook;
    __free_hook = my_free_hook;
    return result;
}

static void my_free_hook(void *ptr, const void *caller)
{
    /* Restore all old hooks */
    __malloc_hook = old_malloc_hook;
    __free_hook = old_free_hook;
    /* Call recursively */
    printf ("freeing pointer %p\n", ptr);
    free(ptr);
    /* we call malloc here, so protect it too. */
    if (malloced.find(ptr) == malloced.end())
    {
        /*fprintf(stderr, "INVALID FREE\n");
        void *trace[16];
        int trace_size = 0;
        trace_size = backtrace(trace, 16);
        backtrace_symbols_fd(trace, trace_size, STDERR_FILENO);*/
    }
    else
        malloced.erase(ptr);
    /* Restore our own hooks */
    __malloc_hook = my_malloc_hook;
    __free_hook = my_free_hook;
}

void memtracing_init()
{
    old_malloc_hook = __malloc_hook;
    old_free_hook = __free_hook;
    __malloc_hook = my_malloc_hook;
    __free_hook = my_free_hook;
}

long gethash(void **trace)
{
    unsigned long hash = 0;
    while (*trace)
    {
        hash = (hash << 1) ^ (hash >> 63) ^ (unsigned long) *trace;
        trace++;
    }
    return hash;
}

void memtracing_kill()
{
    /* Restore all old hooks */
    __malloc_hook = old_malloc_hook;
    __free_hook = old_free_hook;

    map<long, void**> hashToReal;
    map<long, int> counts;
    map<void *, void **>::iterator it = malloced.begin();
    while (it != malloced.end())
    {
        long hash = gethash(it->second);
        hashToReal[hash] = it->second;

        if (counts.find(hash) == counts.end())
            counts[hash] = 1;
        else
            counts[hash]++;

        it++;
    }

    vector<pair<int, long> > sorting;
    map<long, int>::iterator countit = counts.begin();
    while (countit != counts.end())
    {
        sorting.push_back(pair<int, long>(countit->second, countit->first));
        countit++;
    }

    // sort
    bool done = false;
    while (!done)
    {
        done = true;
        for (size_t i = 0; i < sorting.size() - 1; i++)
        {
            if (sorting[i].first < sorting[i + 1].first)
            {
                pair<int, long> t = sorting[i];
                sorting[i] = sorting[i + 1];
                sorting[i + 1] = t;
                done = false;
            }
        }
    }

    for (size_t i = 0; i < sorting.size(); i++)
    {
        long hash = sorting[i].second;
        int count = sorting[i].first;
        char header[256];
        sprintf(header, "--------------------------- LEAKED %d", count);
        print_stackframe(header, hashToReal[hash]);
    }
}
#endif // INSANE_MEMORY_DEBUG

bool run_test(const char *filename)
{
    printf("TEST %s ", filename);
    struct stat results;
    if (!stat(filename, &results) == 0)
    {
        printf("Cannot stat file! '%s'\n", filename);
        return false;
    }
    int size = results.st_size;
    FILE *file = fopen(filename, "rb");
    /* if we open as text, the number of bytes read may be > the size we read */
    if (!file)
    {
        printf("Unable to open file! '%s'\n", filename);
        return false;
    }
    char *buffer = new char[size + 1];
    long actualRead = fread(buffer, 1, size, file);
    buffer[actualRead] = 0;
    buffer[size] = 0;
    fclose(file);

    CTinyJS s;
    registerFunctions(&s);
    registerMathFunctions(&s);
    s.setGlobal("result", jsInt(0));
    try
    {
        s.execute(buffer);
    }
    catch (const CScriptException &e)
    {
        printf("ERROR: %s\n", e.what());
    }
    bool pass = null2undef( s.getGlobal("result") )->toBoolean();

    if (pass)
        printf("PASS\n");
    else
    {
        char fn[64];
        sprintf(fn, "%s.fail.js", filename);
        FILE *f = fopen(fn, "wt");
        if (f)
        {
            std::string symbols = s.dumpJSONSymbols();
            fprintf(f, "%s", symbols.c_str());
            fclose(f);
        }

        printf("FAIL - symbols written to %s\n", fn);
    }

    delete[] buffer;
    return pass;
}

int main(int argc, char **argv)
{
#ifdef MTRACE
    mtrace();
#endif
#ifdef INSANE_MEMORY_DEBUG
    memtracing_init();
#endif
    printf("TinyJS test runner\n");
    printf("USAGE:\n");
    printf("   ./run_tests test.js       : run just one test\n");
    printf("   ./run_tests               : run all tests\n");
    if (argc == 2)
    {
        printf("Running test: %s\n", argv[1]);

        return !run_test(argv[1]);
    }
    else
        printf("Running all tests!\n");

    int test_num = 1;
    int count = 0;
    int passed = 0;

    while (test_num < 1000)
    {
        char fn[32];
        sprintf(fn, "tests/test%03d.js", test_num);
        // check if the file exists - if not, assume we're at the end of our tests
        FILE *f = fopen(fn, "r");
        if (!f) break;
        fclose(f);

        if (run_test(fn))
            passed++;
        count++;
        test_num++;
    }

    printf("Done. %d tests, %d pass, %d fail\n", count, passed, count - passed);
#ifdef INSANE_MEMORY_DEBUG
    memtracing_kill();
#endif

#ifdef _DEBUG
#ifdef _WIN32
    _CrtDumpMemoryLeaks();
#endif
#endif
#ifdef MTRACE
    muntrace();
#endif

    return 0;
}
<|endoftext|>


<commit_before>#ifndef DD_SUBGRADIENT_CALLER_HXX_
#define DD_SUBGRADIENT_CALLER_HXX_

#include <opengm/inference/dualdecomposition/dualdecomposition_subgradient.hxx>
#include <opengm/inference/dynamicprogramming.hxx>
#ifdef WITH_CPLEX
#include <opengm/inference/lpcplex.hxx>
#endif
#include <opengm/inference/graphcut.hxx>
#ifdef WITH_MAXFLOW
#  include <opengm/inference/auxiliary/minstcutkolmogorov.hxx>
#endif

#include "inference_caller_base.hxx"
#include "../argument/argument.hxx"

namespace opengm {
   namespace interface {

      template <class IO, class GM, class ACC>
      class DDSubgradientCaller : public InferenceCallerBase<IO, GM, ACC, DDSubgradientCaller<IO, GM, ACC> >
      {
      protected:
         typedef InferenceCallerBase<IO, GM, ACC,  DDSubgradientCaller<IO, GM, ACC> > BaseClass;
         typedef typename BaseClass::OutputBase OutputBase;

         using BaseClass::addArgument;
         using BaseClass::io_;
         using BaseClass::infer;

         double minimalAbsAccuracy_;
         double minimalRelAccuracy_;
         size_t maximalDualOrder_;
         size_t numberOfBlocks_;
         size_t maximalNumberOfIterations_;
         size_t numberOfThreads_;

         std::string stepsizeRule_;
         std::string decomposition_;
         std::string subInf_;

         // Update Parameters
         double stepsizeStride_;    //updateStride_;
         double stepsizeScale_;     //updateScale_;
         double stepsizeExponent_;  //updateExponent_;
         double stepsizeMin_;       //updateMin_;
         double stepsizeMax_;       //updateMax_;

         virtual void runImpl(GM& model, OutputBase& output, const bool verbose);

      private:
         template<class Parameter> void setParameter(Parameter& p);
      public:
         const static std::string name_;
         DDSubgradientCaller(IO& ioIn);
      };

      template <class IO, class GM, class ACC>
      const std::string DDSubgradientCaller<IO, GM, ACC>::name_ = "DDSubgradient";

      template <class IO, class GM, class ACC>
      inline DDSubgradientCaller<IO, GM, ACC>::DDSubgradientCaller(IO& ioIn)
         : BaseClass("DD-Subgradient", "detailed description of DD-Subgradient Parser...", ioIn)
      {
         addArgument(Size_TArgument<>(maximalNumberOfIterations_,
                                      "", "maxIt", "Maximum number of iterations.", size_t(100)));
         addArgument(DoubleArgument<>(minimalAbsAccuracy_,
                                      "", "absStop", "Stop if primal-dual-gap is smaller than this value", double(0.0)));
         addArgument(DoubleArgument<>(minimalRelAccuracy_,
                                      "", "relStop", "Stop if primal-dual-gap/(|dual|+1) is smale than this value", double(0.0)));
         addArgument(DoubleArgument<>(stepsizeStride_,
                                      "", "ssStride", "stride (s) of stepsize rule", double(1.0)));
         addArgument(DoubleArgument<>(stepsizeScale_,
                                      "", "ssScale", "scale (a) of stepsize rule", double(1.0)));
         addArgument(DoubleArgument<>(stepsizeExponent_,
                                      "", "ssExponent", "exponent (e) of stepsize rule", double(0.5)));
         addArgument(DoubleArgument<>(stepsizeMin_,
                                      "", "ssMin", "minimal stepsize", double(0.0)));
         addArgument(DoubleArgument<>(stepsizeMax_,
                                      "", "ssMax", "maximal stepsize", double(std::numeric_limits<double>::infinity())));
         addArgument(Size_TArgument<>(numberOfBlocks_,
                                      "", "numBlocks", "Number of blocks (subproblems).", size_t(2)));
         addArgument(Size_TArgument<>(numberOfThreads_,
                                      "", "numThreads", "Number of Threads used for primal subproblems", size_t(1)));

         std::vector<std::string> stepsizeRules;
         stepsizeRules.push_back("ProjectedAdaptive");
         stepsizeRules.push_back("Adaptive");
         stepsizeRules.push_back("StepLength");
         stepsizeRules.push_back("StepSize");
         addArgument(StringArgument<>(stepsizeRule_,
                                      "", "stepsizeRule", "Stepsize rule for dual update \n \t\t\t\t\t\t\t* ProjectedAdaptive: primalDualGap/(1+ (a*i)^e)/|P(s)|\n \t\t\t\t\t\t\t* Adaptive:          primalDualGap/(1+ (a*i)^e)/|s|\n \t\t\t\t\t\t\t* StepLength:         s/(1+ (a*i)^e)/|P(s)|\n \t\t\t\t\t\t\t* StepSize:           s/(1+ (a*i)^e)", stepsizeRules[0], stepsizeRules));
         std::vector<std::string> subInfs;
         subInfs.push_back("ILP");
         subInfs.push_back("DPTree");
         subInfs.push_back("GraphCut");
         addArgument(StringArgument<>(subInf_,
                                      "", "subInf", "Algorithm used for subproblems", subInfs[0], subInfs));
         std::vector<std::string> decompositions;
         decompositions.push_back("Tree");
         decompositions.push_back("SpanningTrees");
         decompositions.push_back("Blocks");
         addArgument(StringArgument<>(decomposition_,
                                      "", "decomp", "Type of used decomposition",  decompositions[0], decompositions));

      }

      template <class IO, class GM, class ACC>
      template<class Parameter>
      void DDSubgradientCaller<IO, GM, ACC>::setParameter(Parameter& p)
      {
         p.minimalAbsAccuracy_=minimalAbsAccuracy_;
         p.minimalRelAccuracy_=minimalRelAccuracy_;
         p.maximalDualOrder_=maximalDualOrder_;
         p.numberOfBlocks_=numberOfBlocks_;
         p.maximalNumberOfIterations_=maximalNumberOfIterations_;
         p.numberOfThreads_=numberOfThreads_;

         // Update Parameters
         p.stepsizeStride_=stepsizeStride_;    //updateStride_;
         p.stepsizeScale_=stepsizeScale_;     //updateScale_;
         p.stepsizeExponent_=stepsizeExponent_;  //updateExponent_;
         p.stepsizeMin_=stepsizeMin_;       //updateMin_;
         p.stepsizeMax_=stepsizeMax_;       //updateMax_;

         //UpdateRule
         if(stepsizeRule_.compare("ProjectedAdaptive")==0){
            p.useProjectedAdaptiveStepsize_=true;
            //p.stepsizePrimalDualGapStride_ = true;
            //p.stepsizeNormalizedSubgradient_ = true;
         }else if(stepsizeRule_.compare("Adaptive")==0){
            p.useAdaptiveStepsize_=true;
            //p.stepsizePrimalDualGapStride_ = true;
            //p.stepsizeNormalizedSubgradient_ = false;
         }else if(stepsizeRule_.compare("StepLength")==0){
            p.stepsizePrimalDualGapStride_ = false;
            p.stepsizeNormalizedSubgradient_ = true;
         }else if(stepsizeRule_.compare("StepSize")==0){
            p.stepsizePrimalDualGapStride_ = false;
            p.stepsizeNormalizedSubgradient_ = false;
         }else{
            std::cout << "Unknown stepsize rule !!! " << std::endl;
         }

         //Decompositions
         if(decomposition_.compare("Tree")==0){
            p.decompositionId_=  opengm::DualDecompositionBaseParameter::TREE;
         }else if(decomposition_.compare("SpanningTrees")==0){
            p.decompositionId_= opengm::DualDecompositionBaseParameter::SPANNINGTREES;
         }else if(decomposition_.compare("Blocks")==0){
            p.decompositionId_= opengm::DualDecompositionBaseParameter::BLOCKS;
         }else{
            std::cout << "Unknown decomposition type !!! " << std::endl;
         }
      }

      template <class IO, class GM, class ACC>
      inline void DDSubgradientCaller<IO, GM, ACC>::runImpl(GM& model, OutputBase& output, const bool verbose)
      {
         std::cout << "running DD-Subgradient caller" << std::endl;

         typedef typename GM::ValueType                                                  ValueType;
         typedef opengm::DDDualVariableBlock<marray::View<ValueType, false> >            DualBlockType;
         typedef typename opengm::DualDecompositionBase<GM,DualBlockType>::SubGmType     SubGmType;

         if((*this).subInf_.compare("ILP")==0){
#ifdef WITH_CPLEX
            typedef opengm::LPCplex<SubGmType, ACC>                                 InfType;
            typedef opengm::DualDecompositionSubGradient<GM,InfType,DualBlockType>  DDType;
            typedef typename DDType::TimingVisitorType                              TimingVisitorType;

            typename DDType::Parameter parameter;
            setParameter(parameter);
            parameter.subPara_.integerConstraint_ = true;
            this-> template infer<DDType, TimingVisitorType, typename DDType::Parameter>(model, output, verbose, parameter);
#else
            std::cout << "CPLEX not enabled!!!" <<std::endl;
#endif
         }
         else if((*this).subInf_.compare("DPTree")==0){
            typedef opengm::DynamicProgramming<SubGmType, ACC>                      InfType;
            typedef opengm::DualDecompositionSubGradient<GM,InfType,DualBlockType>  DDType;
            typedef typename DDType::TimingVisitorType                              TimingVisitorType;

            typename DDType::Parameter parameter;
            setParameter(parameter);
            this-> template infer<DDType, TimingVisitorType, typename DDType::Parameter>(model, output, verbose, parameter);
         }
         else if((*this).subInf_.compare("GraphCut")==0){
#ifdef WITH_MAXFLOW
            typedef opengm::external::MinSTCutKolmogorov<size_t, double>            MinStCutType;
            typedef opengm::GraphCut<SubGmType, ACC, MinStCutType>                  InfType;
            typedef opengm::DualDecompositionSubGradient<GM,InfType,DualBlockType>  DDType;
            typedef typename DDType::TimingVisitorType                              TimingVisitorType;

            typename DDType::Parameter parameter;
            setParameter(parameter);
            this-> template infer<DDType, TimingVisitorType, typename DDType::Parameter>(model, output, verbose, parameter);
#else
            std::cout << "MaxFlow not enabled!!!" <<std::endl;
#endif
         }
         else{
            std::cout << "Unknown Sub-Inference-Algorithm !!!" <<std::endl;
         }
      }
   } // namespace interface
} // namespace opengm

#endif /* DDBUNDLE_CALLER_HXX_ */
<commit_msg>add hypertree-solver for subproblems<commit_after>#ifndef DD_SUBGRADIENT_CALLER_HXX_
#define DD_SUBGRADIENT_CALLER_HXX_

#include <opengm/inference/dualdecomposition/dualdecomposition_subgradient.hxx>
#include <opengm/inference/dynamicprogramming.hxx>
#include <opengm/inference/messagepassing/messagepassing.hxx>
#ifdef WITH_CPLEX
#include <opengm/inference/lpcplex.hxx>
#endif
#include <opengm/inference/graphcut.hxx>
#ifdef WITH_MAXFLOW
#  include <opengm/inference/auxiliary/minstcutkolmogorov.hxx>
#endif

#include "inference_caller_base.hxx"
#include "../argument/argument.hxx"

namespace opengm {
   namespace interface {

      template <class IO, class GM, class ACC>
      class DDSubgradientCaller : public InferenceCallerBase<IO, GM, ACC, DDSubgradientCaller<IO, GM, ACC> >
      {
      protected:
         typedef InferenceCallerBase<IO, GM, ACC,  DDSubgradientCaller<IO, GM, ACC> > BaseClass;
         typedef typename BaseClass::OutputBase OutputBase;

         using BaseClass::addArgument;
         using BaseClass::io_;
         using BaseClass::infer;

         double minimalAbsAccuracy_;
         double minimalRelAccuracy_;
         size_t maximalDualOrder_;
         size_t numberOfBlocks_;
         size_t maximalNumberOfIterations_;
         size_t numberOfThreads_;

         std::string stepsizeRule_;
         std::string decomposition_;
         std::string subInf_;

         // Update Parameters
         double stepsizeStride_;    //updateStride_;
         double stepsizeScale_;     //updateScale_;
         double stepsizeExponent_;  //updateExponent_;
         double stepsizeMin_;       //updateMin_;
         double stepsizeMax_;       //updateMax_;

         virtual void runImpl(GM& model, OutputBase& output, const bool verbose);

      private:
         template<class Parameter> void setParameter(Parameter& p);
      public:
         const static std::string name_;
         DDSubgradientCaller(IO& ioIn);
      };

      template <class IO, class GM, class ACC>
      const std::string DDSubgradientCaller<IO, GM, ACC>::name_ = "DDSubgradient";

      template <class IO, class GM, class ACC>
      inline DDSubgradientCaller<IO, GM, ACC>::DDSubgradientCaller(IO& ioIn)
         : BaseClass("DD-Subgradient", "detailed description of DD-Subgradient Parser...", ioIn)
      {
         addArgument(Size_TArgument<>(maximalNumberOfIterations_,
                                      "", "maxIt", "Maximum number of iterations.", size_t(100)));
         addArgument(DoubleArgument<>(minimalAbsAccuracy_,
                                      "", "absStop", "Stop if primal-dual-gap is smaller than this value", double(0.0)));
         addArgument(DoubleArgument<>(minimalRelAccuracy_,
                                      "", "relStop", "Stop if primal-dual-gap/(|dual|+1) is smale than this value", double(0.0)));
         addArgument(DoubleArgument<>(stepsizeStride_,
                                      "", "ssStride", "stride (s) of stepsize rule", double(1.0)));
         addArgument(DoubleArgument<>(stepsizeScale_,
                                      "", "ssScale", "scale (a) of stepsize rule", double(1.0)));
         addArgument(DoubleArgument<>(stepsizeExponent_,
                                      "", "ssExponent", "exponent (e) of stepsize rule", double(0.5)));
         addArgument(DoubleArgument<>(stepsizeMin_,
                                      "", "ssMin", "minimal stepsize", double(0.0)));
         addArgument(DoubleArgument<>(stepsizeMax_,
                                      "", "ssMax", "maximal stepsize", double(std::numeric_limits<double>::infinity())));
         addArgument(Size_TArgument<>(numberOfBlocks_,
                                      "", "numBlocks", "Number of blocks (subproblems).", size_t(2)));
         addArgument(Size_TArgument<>(numberOfThreads_,
                                      "", "numThreads", "Number of Threads used for primal subproblems", size_t(1)));

         std::vector<std::string> stepsizeRules;
         stepsizeRules.push_back("ProjectedAdaptive");
         stepsizeRules.push_back("Adaptive");
         stepsizeRules.push_back("StepLength");
         stepsizeRules.push_back("StepSize");
         addArgument(StringArgument<>(stepsizeRule_,
                                      "", "stepsizeRule", "Stepsize rule for dual update \n \t\t\t\t\t\t\t* ProjectedAdaptive: primalDualGap/(1+ (a*i)^e)/|P(s)|\n \t\t\t\t\t\t\t* Adaptive:          primalDualGap/(1+ (a*i)^e)/|s|\n \t\t\t\t\t\t\t* StepLength:         s/(1+ (a*i)^e)/|P(s)|\n \t\t\t\t\t\t\t* StepSize:           s/(1+ (a*i)^e)", stepsizeRules[0], stepsizeRules));
         std::vector<std::string> subInfs;
         subInfs.push_back("ILP");
         subInfs.push_back("DPTree");
         subInfs.push_back("DPHTree");
         subInfs.push_back("GraphCut");
         addArgument(StringArgument<>(subInf_,
                                      "", "subInf", "Algorithm used for subproblems", subInfs[0], subInfs));
         std::vector<std::string> decompositions;
         decompositions.push_back("Tree");
         decompositions.push_back("SpanningTrees");
         decompositions.push_back("Blocks");
         addArgument(StringArgument<>(decomposition_,
                                      "", "decomp", "Type of used decomposition",  decompositions[0], decompositions));

      }

      template <class IO, class GM, class ACC>
      template<class Parameter>
      void DDSubgradientCaller<IO, GM, ACC>::setParameter(Parameter& p)
      {
         p.minimalAbsAccuracy_=minimalAbsAccuracy_;
         p.minimalRelAccuracy_=minimalRelAccuracy_;
         p.maximalDualOrder_=maximalDualOrder_;
         p.numberOfBlocks_=numberOfBlocks_;
         p.maximalNumberOfIterations_=maximalNumberOfIterations_;
         p.numberOfThreads_=numberOfThreads_;

         // Update Parameters
         p.stepsizeStride_=stepsizeStride_;    //updateStride_;
         p.stepsizeScale_=stepsizeScale_;     //updateScale_;
         p.stepsizeExponent_=stepsizeExponent_;  //updateExponent_;
         p.stepsizeMin_=stepsizeMin_;       //updateMin_;
         p.stepsizeMax_=stepsizeMax_;       //updateMax_;

         //UpdateRule
         if(stepsizeRule_.compare("ProjectedAdaptive")==0){
            p.useProjectedAdaptiveStepsize_=true;
            //p.stepsizePrimalDualGapStride_ = true;
            //p.stepsizeNormalizedSubgradient_ = true;
         }else if(stepsizeRule_.compare("Adaptive")==0){
            p.useAdaptiveStepsize_=true;
            //p.stepsizePrimalDualGapStride_ = true;
            //p.stepsizeNormalizedSubgradient_ = false;
         }else if(stepsizeRule_.compare("StepLength")==0){
            p.stepsizePrimalDualGapStride_ = false;
            p.stepsizeNormalizedSubgradient_ = true;
         }else if(stepsizeRule_.compare("StepSize")==0){
            p.stepsizePrimalDualGapStride_ = false;
            p.stepsizeNormalizedSubgradient_ = false;
         }else{
            std::cout << "Unknown stepsize rule !!! " << std::endl;
         }

         //Decompositions
         if(decomposition_.compare("Tree")==0){
            p.decompositionId_=  opengm::DualDecompositionBaseParameter::TREE;
         }else if(decomposition_.compare("SpanningTrees")==0){
            p.decompositionId_= opengm::DualDecompositionBaseParameter::SPANNINGTREES;
         }else if(decomposition_.compare("Blocks")==0){
            p.decompositionId_= opengm::DualDecompositionBaseParameter::BLOCKS;
         }else{
            std::cout << "Unknown decomposition type !!! " << std::endl;
         }
      }

      template <class IO, class GM, class ACC>
      inline void DDSubgradientCaller<IO, GM, ACC>::runImpl(GM& model, OutputBase& output, const bool verbose)
      {
         std::cout << "running DD-Subgradient caller" << std::endl;

         typedef typename GM::ValueType                                                  ValueType;
         typedef opengm::DDDualVariableBlock<marray::View<ValueType, false> >            DualBlockType;
         typedef typename opengm::DualDecompositionBase<GM,DualBlockType>::SubGmType     SubGmType;

         if((*this).subInf_.compare("ILP")==0){
#ifdef WITH_CPLEX
            typedef opengm::LPCplex<SubGmType, ACC>                                 InfType;
            typedef opengm::DualDecompositionSubGradient<GM,InfType,DualBlockType>  DDType;
            typedef typename DDType::TimingVisitorType                              TimingVisitorType;

            typename DDType::Parameter parameter;
            setParameter(parameter);
            parameter.subPara_.integerConstraint_ = true;
            this-> template infer<DDType, TimingVisitorType, typename DDType::Parameter>(model, output, verbose, parameter);
#else
            std::cout << "CPLEX not enabled!!!" <<std::endl;
#endif
         }
         else if((*this).subInf_.compare("DPTree")==0){
            typedef opengm::DynamicProgramming<SubGmType, ACC>                      InfType;
            typedef opengm::DualDecompositionSubGradient<GM,InfType,DualBlockType>  DDType;
            typedef typename DDType::TimingVisitorType                              TimingVisitorType;

            typename DDType::Parameter parameter;
            setParameter(parameter);
            this-> template infer<DDType, TimingVisitorType, typename DDType::Parameter>(model, output, verbose, parameter);
         }
         else if((*this).subInf_.compare("DPHTree")==0){
            typedef BeliefPropagationUpdateRules<SubGmType, ACC>               UpdateRulesType;
            typedef MessagePassing<SubGmType, ACC, UpdateRulesType>            InfType;
            typedef opengm::DualDecompositionSubGradient<GM,InfType,DualBlockType>  DDType;
            typedef typename DDType::TimingVisitorType                       TimingVisitorType;
            typename DDType::Parameter parameter;
            setParameter(parameter);
            parameter.subPara_.isAcyclic_ = true;
            this-> template infer<DDType, TimingVisitorType, typename DDType::Parameter>(model, output, verbose, parameter);
         }
         else if((*this).subInf_.compare("GraphCut")==0){
#ifdef WITH_MAXFLOW
            typedef opengm::external::MinSTCutKolmogorov<size_t, double>            MinStCutType;
            typedef opengm::GraphCut<SubGmType, ACC, MinStCutType>                  InfType;
            typedef opengm::DualDecompositionSubGradient<GM,InfType,DualBlockType>  DDType;
            typedef typename DDType::TimingVisitorType                              TimingVisitorType;

            typename DDType::Parameter parameter;
            setParameter(parameter);
            this-> template infer<DDType, TimingVisitorType, typename DDType::Parameter>(model, output, verbose, parameter);
#else
            std::cout << "MaxFlow not enabled!!!" <<std::endl;
#endif
         }
         else{
            std::cout << "Unknown Sub-Inference-Algorithm !!!" <<std::endl;
         }
      }
   } // namespace interface
} // namespace opengm

#endif /* DDBUNDLE_CALLER_HXX_ */
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2018 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "BufferedResourceLoader.hxx"
#include "HttpResponseHandler.hxx"
#include "strmap.hxx"
#include "istream/BufferedIstream.hxx"
#include "istream/UnusedPtr.hxx"
#include "pool/pool.hxx"
#include "pool/LeakDetector.hxx"
#include "util/Cancellable.hxx"
#include "stopwatch.hxx"

class BufferedResourceLoader::Request final
    : PoolLeakDetector, Cancellable, BufferedIstreamHandler
{
    struct pool &pool;
    ResourceLoader &next;
    const StopwatchPtr parent_stopwatch;
    const sticky_hash_t session_sticky;
    const char *const cache_tag;
    const char *const site_name;
    const http_method_t method;
    const ResourceAddress &address;
    const http_status_t status;
    StringMap headers;
    const char *const body_etag;
    HttpResponseHandler &handler;

    CancellablePointer cancel_ptr;

public:
    Request(struct pool &_pool, ResourceLoader &_next,
            const StopwatchPtr &_parent_stopwatch,
            sticky_hash_t _session_sticky,
            const char *_cache_tag,
            const char *_site_name,
            http_method_t _method, const ResourceAddress &_address,
            http_status_t _status, StringMap &&_headers,
            const char *_body_etag,
            HttpResponseHandler &_handler,
            CancellablePointer &_cancel_ptr) noexcept
        :PoolLeakDetector(_pool), pool(_pool),
         next(_next), parent_stopwatch(_parent_stopwatch),
         session_sticky(_session_sticky),
         cache_tag(_cache_tag),
         site_name(_site_name),
         method(_method), address(_address),
         status(_status),
         /* copy the headers, because they may come from a
            FilterCacheRequest pool which may be freed before
            BufferedIstream becomes ready */
         headers(pool, _headers),
         body_etag(_body_etag),
         handler(_handler)
    {
        _cancel_ptr = *this;
    }

    void Start(EventLoop &_event_loop, PipeStock *_pipe_stock,
               UnusedIstreamPtr &&body) noexcept {
        NewBufferedIstream(pool, _event_loop, _pipe_stock,
                           *this, std::move(body),
                           cancel_ptr);
    }

private:
    void Destroy() noexcept {
        this->~Request();
    }

    /* virtual methods from class Cancellable */
    void Cancel() noexcept override {
        cancel_ptr.Cancel();
        Destroy();
    }

    /* virtual methods from class BufferedIstreamHandler */
    void OnBufferedIstreamReady(UnusedIstreamPtr i) noexcept override {
        next.SendRequest(pool, parent_stopwatch,
                         session_sticky, cache_tag, site_name,
                         method, address, status, std::move(headers),
                         std::move(i), body_etag,
                         handler, cancel_ptr);
    }

    void OnBufferedIstreamError(std::exception_ptr e) noexcept override {
        handler.InvokeError(std::move(e));
    }
};

void
BufferedResourceLoader::SendRequest(struct pool &pool,
                                    const StopwatchPtr &parent_stopwatch,
                                    sticky_hash_t session_sticky,
                                    const char *cache_tag,
                                    const char *site_name,
                                    http_method_t method,
                                    const ResourceAddress &address,
                                    http_status_t status, StringMap &&headers,
                                    UnusedIstreamPtr body, const char *body_etag,
                                    HttpResponseHandler &handler,
                                    CancellablePointer &cancel_ptr) noexcept
{
    if (body) {
        auto *request = NewFromPool<Request>(pool, pool, next, parent_stopwatch,
                                             session_sticky,
                                             cache_tag, site_name,
                                             method, address,
                                             status, std::move(headers),
                                             body_etag, handler, cancel_ptr);
        request->Start(event_loop, pipe_stock, std::move(body));
    } else {
        next.SendRequest(pool, parent_stopwatch,
                         session_sticky, cache_tag, site_name,
                         method, address, status, std::move(headers),
                         std::move(body), body_etag,
                         handler, cancel_ptr);
    }
}
<commit_msg>BufferedResourceLoader: destroy in BufferedIstreamHandler callbacks<commit_after>/*
 * Copyright 2007-2018 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the
 * distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "BufferedResourceLoader.hxx"
#include "HttpResponseHandler.hxx"
#include "strmap.hxx"
#include "istream/BufferedIstream.hxx"
#include "istream/UnusedPtr.hxx"
#include "pool/pool.hxx"
#include "pool/LeakDetector.hxx"
#include "util/Cancellable.hxx"
#include "stopwatch.hxx"

class BufferedResourceLoader::Request final
    : PoolLeakDetector, Cancellable, BufferedIstreamHandler
{
    struct pool &pool;
    ResourceLoader &next;
    const StopwatchPtr parent_stopwatch;
    const sticky_hash_t session_sticky;
    const char *const cache_tag;
    const char *const site_name;
    const http_method_t method;
    const ResourceAddress &address;
    const http_status_t status;
    StringMap headers;
    const char *const body_etag;
    HttpResponseHandler &handler;

    CancellablePointer cancel_ptr;

public:
    Request(struct pool &_pool, ResourceLoader &_next,
            const StopwatchPtr &_parent_stopwatch,
            sticky_hash_t _session_sticky,
            const char *_cache_tag,
            const char *_site_name,
            http_method_t _method, const ResourceAddress &_address,
            http_status_t _status, StringMap &&_headers,
            const char *_body_etag,
            HttpResponseHandler &_handler,
            CancellablePointer &_cancel_ptr) noexcept
        :PoolLeakDetector(_pool), pool(_pool),
         next(_next), parent_stopwatch(_parent_stopwatch),
         session_sticky(_session_sticky),
         cache_tag(_cache_tag),
         site_name(_site_name),
         method(_method), address(_address),
         status(_status),
         /* copy the headers, because they may come from a
            FilterCacheRequest pool which may be freed before
            BufferedIstream becomes ready */
         headers(pool, _headers),
         body_etag(_body_etag),
         handler(_handler)
    {
        _cancel_ptr = *this;
    }

    void Start(EventLoop &_event_loop, PipeStock *_pipe_stock,
               UnusedIstreamPtr &&body) noexcept {
        NewBufferedIstream(pool, _event_loop, _pipe_stock,
                           *this, std::move(body),
                           cancel_ptr);
    }

private:
    void Destroy() noexcept {
        this->~Request();
    }

    /* virtual methods from class Cancellable */
    void Cancel() noexcept override {
        cancel_ptr.Cancel();
        Destroy();
    }

    /* virtual methods from class BufferedIstreamHandler */
    void OnBufferedIstreamReady(UnusedIstreamPtr i) noexcept override {
        next.SendRequest(pool, parent_stopwatch,
                         session_sticky, cache_tag, site_name,
                         method, address, status, std::move(headers),
                         std::move(i), body_etag,
                         handler, cancel_ptr);

        // TODO: destruct before invoking next.SendRequest()
        Destroy();
    }

    void OnBufferedIstreamError(std::exception_ptr e) noexcept override {
        auto &_handler = handler;
        Destroy();
        _handler.InvokeError(std::move(e));
    }
};

void
BufferedResourceLoader::SendRequest(struct pool &pool,
                                    const StopwatchPtr &parent_stopwatch,
                                    sticky_hash_t session_sticky,
                                    const char *cache_tag,
                                    const char *site_name,
                                    http_method_t method,
                                    const ResourceAddress &address,
                                    http_status_t status, StringMap &&headers,
                                    UnusedIstreamPtr body, const char *body_etag,
                                    HttpResponseHandler &handler,
                                    CancellablePointer &cancel_ptr) noexcept
{
    if (body) {
        auto *request = NewFromPool<Request>(pool, pool, next, parent_stopwatch,
                                             session_sticky,
                                             cache_tag, site_name,
                                             method, address,
                                             status, std::move(headers),
                                             body_etag, handler, cancel_ptr);
        request->Start(event_loop, pipe_stock, std::move(body));
    } else {
        next.SendRequest(pool, parent_stopwatch,
                         session_sticky, cache_tag, site_name,
                         method, address, status, std::move(headers),
                         std::move(body), body_etag,
                         handler, cancel_ptr);
    }
}
<|endoftext|>


<commit_before>/*
 * ReportHandler.cpp
 *
 * This file is part of the XShaderCompiler project (Copyright (c) 2014-2016 by Lukas Hermanns)
 * See "LICENSE.txt" for license information.
 */

#include "ReportHandler.h"
#include "SourceCode.h"

namespace Xsc
{

/*
 * ErrorCode class
 */

ErrorCode::ErrorCode(const HLSLErr errorCode)
{
    if (errorCode != HLSLErr::Unknown)
        str_ = "X" + std::to_string(static_cast<int>(errorCode)) + "=" + ErrToString(errorCode);
}

/*
 * ReportHandler class
 */

ReportHandler::ReportHandler(const std::string& reportTypeName, Log* log) :
    reportTypeName_ { reportTypeName },
    log_            { log           }
{
}

void ReportHandler::Error(const std::string& msg, SourceCode* sourceCode, const SourceArea& area, const ErrorCode& errorCode)
{
    SubmitReport(false, Report::Types::Error, (reportTypeName_ + " error"), msg, sourceCode, area, errorCode);
}

void ReportHandler::ErrorBreak(const std::string& msg, SourceCode* sourceCode, const SourceArea& area, const ErrorCode& errorCode)
{
    SubmitReport(true, Report::Types::Error, (reportTypeName_ + " error"), msg, sourceCode, area, errorCode);
}

void ReportHandler::Warning(const std::string& msg, SourceCode* sourceCode, const SourceArea& area, const ErrorCode& errorCode)
{
    SubmitReport(false, Report::Types::Warning, "warning", msg, sourceCode, area, errorCode);
}

void ReportHandler::WarningBreak(const std::string& msg, SourceCode* sourceCode, const SourceArea& area, const ErrorCode& errorCode)
{
    SubmitReport(true, Report::Types::Warning, "warning", msg, sourceCode, area, errorCode);
}

void ReportHandler::SubmitReport(
    bool breakWithExpection, const Report::Types type, const std::string& typeName,
    const std::string& msg, SourceCode* sourceCode, const SourceArea& area, const ErrorCode& errorCode)
{
    /* Initialize output message */
    auto outputMsg = typeName;

    if (type == Report::Types::Error)
        hasErrors_ = true;

    /* Add source position */
    outputMsg += " (";

    if (!currentFilename_.empty())
    {
        outputMsg += currentFilename_;
        outputMsg += ": ";
    }

    outputMsg += area.pos.ToString();
    outputMsg += ") ";

    /* Add error code */
    if (!errorCode.Get().empty())
        outputMsg += "[" + errorCode.Get() + "] ";

    outputMsg += ": ";
    outputMsg += msg;

    /* Either throw or submit report */
    auto report = MakeReport(type, outputMsg, sourceCode, area);

    if (breakWithExpection)
        throw report;
    else if (log_)
        log_->SumitReport(report);
}

/*
 * ======= Private: =======
 */

Report ReportHandler::MakeReport(
    const Report::Types type, const std::string& msg, SourceCode* sourceCode, const SourceArea& area)
{
    if (sourceCode != nullptr && area.length > 0)
    {
        std::string line, marker;
        if (sourceCode->FetchLineMarker(area, line, marker))
            return Report(type, msg, line, marker);
        else
            return Report(type, msg);
    }
    else
        return Report(type, msg);
}

} // /namespace Xsc

// ================================================================================<commit_msg>Minor change.<commit_after>/*
 * ReportHandler.cpp
 *
 * This file is part of the XShaderCompiler project (Copyright (c) 2014-2016 by Lukas Hermanns)
 * See "LICENSE.txt" for license information.
 */

#include "ReportHandler.h"
#include "SourceCode.h"

namespace Xsc
{

/*
 * ErrorCode class
 */

ErrorCode::ErrorCode(const HLSLErr errorCode)
{
    if (errorCode != HLSLErr::Unknown)
        str_ = "X" + std::to_string(static_cast<int>(errorCode)) + "=" + ErrToString(errorCode);
}

/*
 * ReportHandler class
 */

ReportHandler::ReportHandler(const std::string& reportTypeName, Log* log) :
    reportTypeName_ { reportTypeName },
    log_            { log           }
{
}

void ReportHandler::Error(const std::string& msg, SourceCode* sourceCode, const SourceArea& area, const ErrorCode& errorCode)
{
    SubmitReport(false, Report::Types::Error, (reportTypeName_ + " error"), msg, sourceCode, area, errorCode);
}

void ReportHandler::ErrorBreak(const std::string& msg, SourceCode* sourceCode, const SourceArea& area, const ErrorCode& errorCode)
{
    SubmitReport(true, Report::Types::Error, (reportTypeName_ + " error"), msg, sourceCode, area, errorCode);
}

void ReportHandler::Warning(const std::string& msg, SourceCode* sourceCode, const SourceArea& area, const ErrorCode& errorCode)
{
    SubmitReport(false, Report::Types::Warning, "warning", msg, sourceCode, area, errorCode);
}

void ReportHandler::WarningBreak(const std::string& msg, SourceCode* sourceCode, const SourceArea& area, const ErrorCode& errorCode)
{
    SubmitReport(true, Report::Types::Warning, "warning", msg, sourceCode, area, errorCode);
}

void ReportHandler::SubmitReport(
    bool breakWithExpection, const Report::Types type, const std::string& typeName,
    const std::string& msg, SourceCode* sourceCode, const SourceArea& area, const ErrorCode& errorCode)
{
    /* Initialize output message */
    auto outputMsg = typeName;

    if (type == Report::Types::Error)
        hasErrors_ = true;

    /* Add source position */
    outputMsg += " (";

    if (!currentFilename_.empty())
    {
        outputMsg += currentFilename_;
        outputMsg += ":";
    }

    outputMsg += area.pos.ToString();
    outputMsg += ") ";

    /* Add error code */
    if (!errorCode.Get().empty())
        outputMsg += "[" + errorCode.Get() + "] ";

    outputMsg += ": ";
    outputMsg += msg;

    /* Either throw or submit report */
    auto report = MakeReport(type, outputMsg, sourceCode, area);

    if (breakWithExpection)
        throw report;
    else if (log_)
        log_->SumitReport(report);
}

/*
 * ======= Private: =======
 */

Report ReportHandler::MakeReport(
    const Report::Types type, const std::string& msg, SourceCode* sourceCode, const SourceArea& area)
{
    if (sourceCode != nullptr && area.length > 0)
    {
        std::string line, marker;
        if (sourceCode->FetchLineMarker(area, line, marker))
            return Report(type, msg, line, marker);
        else
            return Report(type, msg);
    }
    else
        return Report(type, msg);
}

} // /namespace Xsc

// ================================================================================<|endoftext|>


<commit_before><commit_msg>Inline all non-entry-point functions<commit_after><|endoftext|>


<commit_before>#include <stdlib.h>
#include "v8.h"
#include "node.h"
#include "node_buffer.h"

using namespace v8;
using namespace node;

namespace {

/*
 * Test struct definition used in the test harness functions below.
 */

typedef struct box {
  int width;
  int height;
} _box;

/*
 * Accepts a struct by value, and returns a struct by value.
 */

box double_box(box input) {
  box rtn;
  // modify the input box, ensure on the JS side that it's not altered
  input.width *= 2;
  input.height *= 2;
  rtn.width = input.width;
  rtn.height = input.height;
  return rtn;
}

/*
 * Accepts a box struct pointer, and returns a struct by value.
 */

box double_box_ptr(box *input) {
  box rtn;
  // modify the input box, ensure on the JS side that IT IS altered
  input->width *= 2;
  input->height *= 2;
  rtn.width = input->width;
  rtn.height = input->height;
  return rtn;
}

/*
 * Accepts a struct by value, and returns an int.
 */

int area_box(box input) {
  return input.width * input.height;
}

/*
 * Accepts a box pointer and returns an int.
 */

int area_box_ptr(box *input) {
  return input->width * input->height;
}

/*
 * Creates a box and returns it by value.
 */

box create_box(int width, int height) {
  box rtn = { width, height };
  return rtn;
}

/*
 * Creates a box that has the sum of the width and height for its own values.
 */

box add_boxes(box boxes[], int num) {
  box rtn = { 0, 0 };
  box cur;
  for (int i = 0; i < num; i++) {
    cur = boxes[i];
    rtn.width += cur.width;
    rtn.height += cur.height;
  }
  return rtn;
}

/*
 * Hard-coded `strtoul` binding, for the benchmarks.
 *
 * args[0] - the string number to convert to a real Number
 * args[1] - a "buffer" instance to write into (the "endptr")
 * args[2] - the base (0 means autodetect)
 */

Handle<Value> Strtoul(const Arguments &args) {
  HandleScope scope;
  char buf[128];
  int base;
  char **endptr;

  args[0]->ToString()->WriteUtf8(buf);

  Local<Value> endptr_arg = args[0];
  endptr = (char **)Buffer::Data(endptr_arg.As<Object>());

  base = args[2]->Int32Value();

  unsigned long val = strtoul(buf, endptr, base);

  return scope.Close(Integer::NewFromUnsigned(val));
}

// experiments for #72
typedef void (*cb)(void);

static cb callback = NULL;

Handle<Value> SetCb(const Arguments &args) {
  HandleScope scope;
  char *buf = Buffer::Data(args[0].As<Object>());
  callback = (cb)buf;
  return scope.Close(Undefined());
}

Handle<Value> CallCb(const Arguments &args) {
  if (callback == NULL) {
    return ThrowException(Exception::Error(String::New("you must call \"set_cb()\" first")));
  } else {
    callback();
  }
  return Undefined();
}

void AsyncCbCall(uv_work_t *req) {
  callback();
}

void FinishAsyncCbCall(uv_work_t *req) {
  // nothing
  delete req;
}

Handle<Value> CallCbAsync(const Arguments &args) {
  if (callback == NULL) {
    return ThrowException(Exception::Error(String::New("you must call \"set_cb()\" first")));
  } else {
    uv_work_t *req = new uv_work_t;
    uv_queue_work(uv_default_loop(), req, AsyncCbCall, FinishAsyncCbCall);
  }
  return Undefined();
}

void wrap_pointer_cb(char *data, void *hint) {
  //fprintf(stderr, "wrap_pointer_cb\n");
}

Handle<Object> WrapPointer(char *ptr) {
  void *user_data = NULL;
  size_t length = 0;
  Buffer *buf = Buffer::New(ptr, length, wrap_pointer_cb, user_data);
  return buf->handle_;
}

void Initialize(Handle<Object> target) {
  HandleScope scope;

  // atoi and abs here for testing purposes
  target->Set(String::NewSymbol("atoi"), WrapPointer((char *)atoi));

  // Windows has multiple `abs` signatures, so we need to manually disambiguate
  int (*absPtr)(int)(abs);
  target->Set(String::NewSymbol("abs"),  WrapPointer((char *)absPtr));

  // sprintf pointer; used in the varadic tests
  target->Set(String::NewSymbol("sprintf"),  WrapPointer((char *)sprintf));

  // hard-coded `strtoul` binding, for the benchmarks
  NODE_SET_METHOD(target, "strtoul", Strtoul);

  NODE_SET_METHOD(target, "set_cb", SetCb);
  NODE_SET_METHOD(target, "call_cb", CallCb);
  NODE_SET_METHOD(target, "call_cb_async", CallCbAsync);

  // also need to test these custom functions
  target->Set(String::NewSymbol("double_box"), WrapPointer((char *)double_box));
  target->Set(String::NewSymbol("double_box_ptr"), WrapPointer((char *)double_box_ptr));
  target->Set(String::NewSymbol("area_box"), WrapPointer((char *)area_box));
  target->Set(String::NewSymbol("area_box_ptr"), WrapPointer((char *)area_box_ptr));
  target->Set(String::NewSymbol("create_box"), WrapPointer((char *)create_box));
  target->Set(String::NewSymbol("add_boxes"), WrapPointer((char *)add_boxes));
}

} // anonymous namespace

NODE_MODULE(ffi_tests, Initialize);
<commit_msg>test: fix failing sprintf() test on Windows<commit_after>#include <stdlib.h>
#include "v8.h"
#include "node.h"
#include "node_buffer.h"

using namespace v8;
using namespace node;

namespace {

/*
 * Test struct definition used in the test harness functions below.
 */

typedef struct box {
  int width;
  int height;
} _box;

/*
 * Accepts a struct by value, and returns a struct by value.
 */

box double_box(box input) {
  box rtn;
  // modify the input box, ensure on the JS side that it's not altered
  input.width *= 2;
  input.height *= 2;
  rtn.width = input.width;
  rtn.height = input.height;
  return rtn;
}

/*
 * Accepts a box struct pointer, and returns a struct by value.
 */

box double_box_ptr(box *input) {
  box rtn;
  // modify the input box, ensure on the JS side that IT IS altered
  input->width *= 2;
  input->height *= 2;
  rtn.width = input->width;
  rtn.height = input->height;
  return rtn;
}

/*
 * Accepts a struct by value, and returns an int.
 */

int area_box(box input) {
  return input.width * input.height;
}

/*
 * Accepts a box pointer and returns an int.
 */

int area_box_ptr(box *input) {
  return input->width * input->height;
}

/*
 * Creates a box and returns it by value.
 */

box create_box(int width, int height) {
  box rtn = { width, height };
  return rtn;
}

/*
 * Creates a box that has the sum of the width and height for its own values.
 */

box add_boxes(box boxes[], int num) {
  box rtn = { 0, 0 };
  box cur;
  for (int i = 0; i < num; i++) {
    cur = boxes[i];
    rtn.width += cur.width;
    rtn.height += cur.height;
  }
  return rtn;
}

/*
 * Hard-coded `strtoul` binding, for the benchmarks.
 *
 * args[0] - the string number to convert to a real Number
 * args[1] - a "buffer" instance to write into (the "endptr")
 * args[2] - the base (0 means autodetect)
 */

Handle<Value> Strtoul(const Arguments &args) {
  HandleScope scope;
  char buf[128];
  int base;
  char **endptr;

  args[0]->ToString()->WriteUtf8(buf);

  Local<Value> endptr_arg = args[0];
  endptr = (char **)Buffer::Data(endptr_arg.As<Object>());

  base = args[2]->Int32Value();

  unsigned long val = strtoul(buf, endptr, base);

  return scope.Close(Integer::NewFromUnsigned(val));
}

// experiments for #72
typedef void (*cb)(void);

static cb callback = NULL;

Handle<Value> SetCb(const Arguments &args) {
  HandleScope scope;
  char *buf = Buffer::Data(args[0].As<Object>());
  callback = (cb)buf;
  return scope.Close(Undefined());
}

Handle<Value> CallCb(const Arguments &args) {
  if (callback == NULL) {
    return ThrowException(Exception::Error(String::New("you must call \"set_cb()\" first")));
  } else {
    callback();
  }
  return Undefined();
}

void AsyncCbCall(uv_work_t *req) {
  callback();
}

void FinishAsyncCbCall(uv_work_t *req) {
  // nothing
  delete req;
}

Handle<Value> CallCbAsync(const Arguments &args) {
  if (callback == NULL) {
    return ThrowException(Exception::Error(String::New("you must call \"set_cb()\" first")));
  } else {
    uv_work_t *req = new uv_work_t;
    uv_queue_work(uv_default_loop(), req, AsyncCbCall, FinishAsyncCbCall);
  }
  return Undefined();
}

void wrap_pointer_cb(char *data, void *hint) {
  //fprintf(stderr, "wrap_pointer_cb\n");
}

Handle<Object> WrapPointer(char *ptr) {
  void *user_data = NULL;
  size_t length = 0;
  Buffer *buf = Buffer::New(ptr, length, wrap_pointer_cb, user_data);
  return buf->handle_;
}

void Initialize(Handle<Object> target) {
  HandleScope scope;

#if WIN32
  // initialize "floating point support" on Windows?!?!
  // (this is some serious bullshit...)
  // http://support.microsoft.com/kb/37507
  float x = 2.3f;
#endif

  // atoi and abs here for testing purposes
  target->Set(String::NewSymbol("atoi"), WrapPointer((char *)atoi));

  // Windows has multiple `abs` signatures, so we need to manually disambiguate
  int (*absPtr)(int)(abs);
  target->Set(String::NewSymbol("abs"),  WrapPointer((char *)absPtr));

  // sprintf pointer; used in the varadic tests
  target->Set(String::NewSymbol("sprintf"),  WrapPointer((char *)sprintf));

  // hard-coded `strtoul` binding, for the benchmarks
  NODE_SET_METHOD(target, "strtoul", Strtoul);

  NODE_SET_METHOD(target, "set_cb", SetCb);
  NODE_SET_METHOD(target, "call_cb", CallCb);
  NODE_SET_METHOD(target, "call_cb_async", CallCbAsync);

  // also need to test these custom functions
  target->Set(String::NewSymbol("double_box"), WrapPointer((char *)double_box));
  target->Set(String::NewSymbol("double_box_ptr"), WrapPointer((char *)double_box_ptr));
  target->Set(String::NewSymbol("area_box"), WrapPointer((char *)area_box));
  target->Set(String::NewSymbol("area_box_ptr"), WrapPointer((char *)area_box_ptr));
  target->Set(String::NewSymbol("create_box"), WrapPointer((char *)create_box));
  target->Set(String::NewSymbol("add_boxes"), WrapPointer((char *)add_boxes));
}

} // anonymous namespace

NODE_MODULE(ffi_tests, Initialize);
<|endoftext|>


<commit_before>#include "all.h"

void Graph::addNoodle(Endpoint from, Endpoint to)
{
	debug("addNoodle: %s[%s](@%p) -> %s[%s](@%p)\n",
		from.block->name(), from.port, from.block,
		to.block->name(), to.port, to.block);

	vertex_t vert_from, vert_to;
	bool found_from = false, found_to = false;

	/* see if the from or to vertex (or both) is already in the graph */
	auto v_it = vertices(m_graph);
	for (auto it = v_it.first; it != v_it.second; ++it)
	{
		vertex_t v = *it;

		if (m_graph[v] == from.block)
		{
			debug("- block %s(@%p) is already in the graph.\n",
				from.block->name(), from.block);

			vert_from = v;
			found_from = true;
		}
		if (m_graph[v] == to.block)
		{
			debug("- block %s(@%p) is already in the graph.\n",
				to.block->name(), to.block);

			vert_to = v;
			found_to = true;
		}

		if (found_from && found_to) break;
	}

	/* add new vertex(es) to the graph if necessary */
	if (!found_from)
	{
		debug("- block %s(@%p) is not in the graph; adding now.\n",
				from.block->name(), from.block);

		vert_from = add_vertex(m_graph);
		m_graph[vert_from] = from.block;
	}
	if (!found_to)
	{
		debug("- block %s(@%p) is not in the graph; adding now.\n",
				to.block->name(), to.block);

		vert_to = add_vertex(m_graph);
		m_graph[vert_to] = to.block;
	}

	debug("- attempting to connect noodle.\n");

	/* the connect functions will ensure that this is not a duplicate noodle and
	 * that inputs are not connected to multiple noodles */
	Noodle *noodle = new Noodle(from.port, to.port);
	from.block->outputs.connect(from.port, noodle);
	to.block->inputs.connect(to.port, noodle);

	debug("- adding noodle to the graph.\n");

	edge_t edge;
	bool result;

	tie(edge, result) = add_edge(vert_from, vert_to, m_graph);
	assert(result);
	m_graph[edge] = noodle;

	dumpGraph();

	m_needCheck = true;
}

int Graph::checkGraph(void)
{
	debug("checkGraph: checking graph validity\n");

	int errors = 0;

	auto e_it = edges(m_graph);
	if (e_it.first == e_it.second)
	{
		throw EmptyGraphException();
		++errors;
	}

	// TODO: check for nodes with no edges (error) [is this possible?]
	// TODO: warn about nodes with unconnected inputs or outputs

	if (errors == 0)
	{
		m_needCheck = false;
	}

	debug("- %d errors\n", errors);
	return errors;
}

void Graph::dumpGraph(void)
{
	/* don't waste time accessing stuff that we won't print */
	if (!verbose) return;

	debug("\n======================= graph summary =======================\n");

	debug("%lu blocks\n", num_vertices(m_graph));
	auto v_it = vertices(m_graph);
	for (auto it = v_it.first; it != v_it.second; ++it)
	{
		vertex_t v = *it;
		Block *b = m_graph[v];
		debug("+ block: %s(@%p)\n", b->name(), b);
	}

	debug("\n%lu noodles\n", num_edges(m_graph));
	auto e_it = edges(m_graph);
	for (auto it = e_it.first; it != e_it.second; ++it)
	{
		edge_t e = *it;
		Noodle *n = m_graph[e];

		vertex_t v1 = source(e, m_graph);
		vertex_t v2 = target(e, m_graph);

		Block *b1 = m_graph[v1];
		Block *b2 = m_graph[v2];

		debug("+ noodle: %s[%s](@%p) -> %s[%s](@%p)\n",
			b1->name(), n->m_fromPort, b1,
			b2->name(), n->m_toPort, b2);
	}

	debug("=============================================================\n\n");
}

void Graph::run(void)
{
	if (m_needCheck)
	{
		if (checkGraph() != 0)
		{
			throw GraphInvalidException();
		}
	}

	/* Call work on all blocks */
	auto v_it = vertices(m_graph);
	for (auto it = v_it.first; it != v_it.second; ++it)
	{
		vertex_t v = *it;
		Block *b = m_graph[v];
		debug("run: calling work on block %s(@%p)\n", b->name(), b);
		b->work();
	}

#if 0
	/* Pass samples between blocks. As currently written, no attempt is made
	 * to handle blocks with multiple inputs or multiple outputs. */
	v_it = vertices(m_graph);
	for (auto it = v_it.first; it != v_it.second; ++it)
	{
		vertex_t v = *it;
		debug("run: on block %p\n", m_graph[v]);

		/* iterator over all outbound edges */
		auto e_it = out_edges(v, m_graph);

		/* This means there are no outbound edges */
		if (e_it.first == e_it.second)
		{
			continue;
		}

		while (!m_graph[v]->outputEmpty())
		{
			int sample = m_graph[v]->popOutput();

			/* Iterate over all outbound edges. */
			for (auto ei = e_it.first; ei != e_it.second; ++ei)
			{
				vertex_t v_sink = target(*ei, m_graph);
				auto conn = m_graph[*ei];
				debug("-- pushing sample %d to block %p input %d"
					" (but actually input 0 for now)\n",
					sample, m_graph[v_sink], conn.second);
				m_graph[v_sink]->pushInput(sample/*, conn.second*/);
			}
		}
	}
#endif
}
<commit_msg>remove TODO for unconnected ports (checks now exist in Block.cpp)<commit_after>#include "all.h"

void Graph::addNoodle(Endpoint from, Endpoint to)
{
	debug("addNoodle: %s[%s](@%p) -> %s[%s](@%p)\n",
		from.block->name(), from.port, from.block,
		to.block->name(), to.port, to.block);

	vertex_t vert_from, vert_to;
	bool found_from = false, found_to = false;

	/* see if the from or to vertex (or both) is already in the graph */
	auto v_it = vertices(m_graph);
	for (auto it = v_it.first; it != v_it.second; ++it)
	{
		vertex_t v = *it;

		if (m_graph[v] == from.block)
		{
			debug("- block %s(@%p) is already in the graph.\n",
				from.block->name(), from.block);

			vert_from = v;
			found_from = true;
		}
		if (m_graph[v] == to.block)
		{
			debug("- block %s(@%p) is already in the graph.\n",
				to.block->name(), to.block);

			vert_to = v;
			found_to = true;
		}

		if (found_from && found_to) break;
	}

	/* add new vertex(es) to the graph if necessary */
	if (!found_from)
	{
		debug("- block %s(@%p) is not in the graph; adding now.\n",
				from.block->name(), from.block);

		vert_from = add_vertex(m_graph);
		m_graph[vert_from] = from.block;
	}
	if (!found_to)
	{
		debug("- block %s(@%p) is not in the graph; adding now.\n",
				to.block->name(), to.block);

		vert_to = add_vertex(m_graph);
		m_graph[vert_to] = to.block;
	}

	debug("- attempting to connect noodle.\n");

	/* the connect functions will ensure that this is not a duplicate noodle and
	 * that inputs are not connected to multiple noodles */
	Noodle *noodle = new Noodle(from.port, to.port);
	from.block->outputs.connect(from.port, noodle);
	to.block->inputs.connect(to.port, noodle);

	debug("- adding noodle to the graph.\n");

	edge_t edge;
	bool result;

	tie(edge, result) = add_edge(vert_from, vert_to, m_graph);
	assert(result);
	m_graph[edge] = noodle;

	dumpGraph();

	m_needCheck = true;
}

int Graph::checkGraph(void)
{
	debug("checkGraph: checking graph validity\n");

	int errors = 0;

	auto e_it = edges(m_graph);
	if (e_it.first == e_it.second)
	{
		throw EmptyGraphException();
		++errors;
	}

	// TODO: check for nodes with no edges (error) [is this possible?]

	if (errors == 0)
	{
		m_needCheck = false;
	}

	debug("- %d errors\n", errors);
	return errors;
}

void Graph::dumpGraph(void)
{
	/* don't waste time accessing stuff that we won't print */
	if (!verbose) return;

	debug("\n======================= graph summary =======================\n");

	debug("%lu blocks\n", num_vertices(m_graph));
	auto v_it = vertices(m_graph);
	for (auto it = v_it.first; it != v_it.second; ++it)
	{
		vertex_t v = *it;
		Block *b = m_graph[v];
		debug("+ block: %s(@%p)\n", b->name(), b);
	}

	debug("\n%lu noodles\n", num_edges(m_graph));
	auto e_it = edges(m_graph);
	for (auto it = e_it.first; it != e_it.second; ++it)
	{
		edge_t e = *it;
		Noodle *n = m_graph[e];

		vertex_t v1 = source(e, m_graph);
		vertex_t v2 = target(e, m_graph);

		Block *b1 = m_graph[v1];
		Block *b2 = m_graph[v2];

		debug("+ noodle: %s[%s](@%p) -> %s[%s](@%p)\n",
			b1->name(), n->m_fromPort, b1,
			b2->name(), n->m_toPort, b2);
	}

	debug("=============================================================\n\n");
}

void Graph::run(void)
{
	if (m_needCheck)
	{
		if (checkGraph() != 0)
		{
			throw GraphInvalidException();
		}
	}

	/* Call work on all blocks */
	auto v_it = vertices(m_graph);
	for (auto it = v_it.first; it != v_it.second; ++it)
	{
		vertex_t v = *it;
		Block *b = m_graph[v];
		debug("run: calling work on block %s(@%p)\n", b->name(), b);
		b->work();
	}

#if 0
	/* Pass samples between blocks. As currently written, no attempt is made
	 * to handle blocks with multiple inputs or multiple outputs. */
	v_it = vertices(m_graph);
	for (auto it = v_it.first; it != v_it.second; ++it)
	{
		vertex_t v = *it;
		debug("run: on block %p\n", m_graph[v]);

		/* iterator over all outbound edges */
		auto e_it = out_edges(v, m_graph);

		/* This means there are no outbound edges */
		if (e_it.first == e_it.second)
		{
			continue;
		}

		while (!m_graph[v]->outputEmpty())
		{
			int sample = m_graph[v]->popOutput();

			/* Iterate over all outbound edges. */
			for (auto ei = e_it.first; ei != e_it.second; ++ei)
			{
				vertex_t v_sink = target(*ei, m_graph);
				auto conn = m_graph[*ei];
				debug("-- pushing sample %d to block %p input %d"
					" (but actually input 0 for now)\n",
					sample, m_graph[v_sink], conn.second);
				m_graph[v_sink]->pushInput(sample/*, conn.second*/);
			}
		}
	}
#endif
}
<|endoftext|>