<commit_before>///
/// \file smallk.hpp
///
/// \brief The smallk API header file.
///
/// Copyright 2014 Georgia Institute of Technology
///
/// 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.

#pragma once

#include <string>
#include <vector>

#define SMALLK_MAJOR_VERSION 1
#define SMALLK_MINOR_VERSION 6
#define SMALLK_PATCH_LEVEL   0

namespace smallk
{
    ///
    /// The NMF algorithms supported by this API.
    ///
    enum Algorithm
    {
        MU,      ///< Multiplicative Updating, Lee & Seung
        BPP,     ///< Block Principal Pivoting, Kim and Park
        HALS,    ///< Hierarchical Alternating Least Squares, Cichocki & Pan
        RANK2    ///< Rank2, Kuang and Park
    };

    ///
    /// The output file formats supported by the clustering code.
    ///
    enum OutputFormat
    {
        XML,  ///< Extensible Markup Language
        JSON  ///< JavaScript Object Notation
    };

    /// \name Initialization and Cleanup
    //@{
    ///
    /// \brief Perform initialization - call this function first.
    ///
    /// Simply pass \c argc and \c argv from \c main to this function.
    ///
    /// \param[in] argc The number of command-line arguments.
    /// \param[in] argv The array of command-line argument strings.
    void Initialize(int& argc, char**& argv);

    ///
    /// \brief Determine whether the library has been initialized.
    /// \return A boolean indicating the initialization status.
    bool IsInitialized();

    ///
    /// \brief Perform cleanup - call this function last.
    void Finalize();
    //@}

    /// \name Versioning
    //@{
    ///
    /// \brief Returns the API major version.
    /// \return The major version number as an \c unsigned \c int.
    unsigned int GetMajorVersion();

    /// \brief Returns the API minor version.
    /// \return The minor version number as an \c unsigned \c int.
    unsigned int GetMinorVersion();

    /// \brief Returns the API patch level.
    /// \return The patch level as an \c unsigned \c int.
    unsigned int GetPatchLevel();

    /// \brief Returns the API version string.
    /// \return The version string formatted as \c major_version.minor_version.patch_level.
    std::string GetVersionString();
    //@}

    /// \name Common Functions
    //@{
    ///
    /// \brief Returns the precision with which output files will be written.
    /// \return The number of digits after the decimal point for elements of matrices \c W and \c H.
    unsigned int GetOutputPrecision();

    ///
    /// \brief Sets the precision with which output files will be written.
    /// \param[in] num_digits The desired number of digits after the decimal point.
    void SetOutputPrecision(const unsigned int num_digits = 6);

    ///
    /// \brief Returns the tolerance value used to terminate iterative NMF algorithms.
    /// \return The tolerance as a double-precision floating point number.
    ///
    /// The NMF algorithms used by smallk are iterative.  At each iteration, a metric
    /// is computed that estimates the progress made towards a solution.  The metrics
    /// are designed to decrease as the computation progresses.  The 'tolerance' parameter
    /// is the cutoff value for this metric, meaning that whenever the metric decreases
    /// to this value the iterations are terminated and the solution is said to have converged.
    /// There is a tradeoff between the maximum number of iterations and the tolerance.
    /// Smaller values of the tolerance generally require more iterations.
    double GetNmfTolerance();

    ///
    /// \brief Sets the cutoff tolerance for NMF iterations.
    /// \param[in] tol The tolerance value.
    void SetNmfTolerance(const double tol = 0.005);

    ///
    /// \brief Returns the maximum number of iterations allowed for either NMF or clustering.
    /// \return The iteration count as an unsigned integer.
    unsigned int GetMaxIter();

    ///
    /// \brief Sets the upper limit to the number of iterations for NMF and clustering.
    /// \param[in] max_iterations The maximum number of iterations to perform.
    void SetMaxIter(const unsigned int max_iterations = 5000);

    ///
    /// \brief Returns the minimum number of iterations performed by either the NMF or clustering code.
    /// \return The iteration count as an unsigned integer.
    unsigned int GetMinIter();

    ///
    /// \brief Sets the minimum number of iterations to be performed by either the NMF or clustering code.
    /// \param[in] min_iterations The minimum number of iterations to perform.
    void SetMinIter(const unsigned int min_iterations = 5);

    ///
    /// \brief Returns the maximum number of threads used for either the NMF or clustering computations.
    /// \return The thread count as an unsigned integer.
    unsigned int GetMaxThreads();

    ///
    /// \brief Sets an upper limit to the number of threads used by either the NMF or clustering code.
    /// \param[in] max_threads The maximum number of threads to use.
    ///
    /// The smallk code is multithreaded for improved performance.  The default upper limit
    /// to the number of threads used by the code is determined by the hardware's capabilities.
    /// Use this function to override this limit and restrict the thread count to a smaller range.
    /// Allowable values for max_threads are in the interval [1, hardware_max_threads].
    void SetMaxThreads(const unsigned int max_threads);

    ///
    /// \brief Sets all params to default values and clears any loaded matrices.
    void Reset();

    ///
    /// \brief Seed the random number generator with the specified value.
    /// \param[in] seed An integer seed value.
    void SeedRNG(const int seed);

    ///
    /// \brief Load the matrix to be factored from a file.
    /// \param[in] filepath The absolute or relative path to a matrix file.
    ///
    /// The smallk code can read matrix files in either CSV (comma separated value)
    /// or MTX (MatrixMarket) format.  CSV files are assumed to contain dense
    /// matrices, i.e. the CSV files must contain an entry for each matrix element.
    /// MTX files are assumed to contain sparse matrices only.
    void LoadMatrix(const std::string& filepath);

    ///
    /// \brief Load the dense matrix to be factored from a buffer.
    /// \param[in] buffer A pointer to the buffer containing the input matrix.
    /// \param[in] ldim The leading dimension of the input matrix buffer.
    /// \param[in] height The height of the input matrix.
    /// \param[in] width The width of the input matrixe.
    ///
    /// The smallk code can read dense matrix files from a pointer to a buffer.
    /// This can be used for passing in a matrix generated in python.
    void LoadMatrix(const double *buffer,
                    const unsigned int ldim,
                    const unsigned int height,
                    const unsigned int width);
    ///
    /// \brief Load the sparse matrix to be factored from a buffer.
    /// \param[in] height The height of the input matrix.
    /// \param[in] width The width of the input matrixe.
    /// \param[in] nz The number of non-zero entries in the matrix.
    /// \param[in] data A reference to the vector containing the non-zero input data.
    /// \param[in] row_indices A reference to the row_indicies vector.
    /// \param[in] col_offsets A reference to the col_offsets vector.
    ///
    /// The smallk code can read dense matrix files from a pointer to a buffer.
    /// This can be used for passing in a matrix generated in python.
    void LoadMatrix(const unsigned int height,
                    const unsigned int width,
                    const unsigned int nz,
                    const std::vector<double>& data,
                    const std::vector<unsigned int>& row_indices,
                    const std::vector<unsigned int>& col_offsets);

    ///
    /// \brief Returns whether a CSV or MTX file has been successfully loaded.
    /// \return A boolean indicating the presence or absence of a loaded matrix.
    bool IsMatrixLoaded();

    ///
    /// \brief Returns the output directory where result files will be written.
    /// \return A string representing the output directory.
    std::string GetOutputDir();

    ///
    /// \brief Sets the directory into which result files will be written.
    /// \param[in] outdir The absolute or relative path to an output directory.
    ///
    /// The otuput directory must exist - the smallk code will not create it.
    void SetOutputDir(const std::string& outdir);

    //@}

    /// \name NMF
    //@{
    ///
    /// \brief Runs the selected NMF algorithm on the loaded matrix.
    /// \param[in] k The width of matrix W or the height of matrix H.
    /// \param[in] algorithm The desired NMF algorithm.
    /// \param[in] initfile_w A CSV file containing initial values for \c m x \c k matrix W.
    /// \param[in] initfile_h A CSV file containing initial values for \c k x \c n matrix H.
    /// This function performs the factorization \c A \c ~ \c W \c H, where
    /// matrix A is \c m x \c n, matrix W is \c m x \c k, and matrix H is
    /// \c k x \c n.  Matrix A must have already been loaded by a prior
    /// call to \c LoadMatrix.
    void Nmf(const unsigned int k,
             const Algorithm algorithm = BPP,
             const std::string& initfile_w = std::string(""),
             const std::string& initfile_h = std::string(""));

    ///
    /// \brief Returns a pointer to the buffer containing the NMF result matrix W.
    /// \param[out] ldim The leading dimension of the W-buffer.
    /// \param[out] height The height of the W matrix.
    /// \param[out] width The width of the W matrix.
    const double* LockedBufferW(unsigned int& ldim,
                                unsigned int& height,
                                unsigned int& width);

    ///
    /// \brief Returns a pointer to the buffer containing the NMF result matrix H.
    /// \param[out] ldim The leading dimension of the H-buffer.
    /// \param[out] height The height of the H matrix.
    /// \param[out] width The width of the H matrix.
    const double* LockedBufferH(unsigned int& ldim,
                                unsigned int& height,
                                unsigned int& width);

    //@}

    /// \name Clustering
    //{@
    ///
    /// \brief Load the file containing the dictionary strings.
    /// \param[in] filepath The absolute or relative path to the dictionary file.
    /// Each row of the term-frequency matrix represents a 'term' in the dictionary.
    /// The dictionary file is the collection of all such terms, one per line.
    /// A 'term' can consist of multiple words.  The smallk code considers each individual
    /// line in the file a separate term.
    ///
    void LoadDictionary(const std::string& filepath);

    ///
    /// \brief Load the file containing the dictionary strings.
    /// \param[in] terms The vector containing the dictionary terms.
    ///
    void LoadDictionary(const std::vector<std::string>& terms);

    ///
    /// \brief Reuturns the maximum number of terms computed per node during clustering.
    /// \return The term count as an unsigned int.
    unsigned int GetMaxTerms();

    ///
    /// \brief Set the maximum number of terms to compute per node during clustering.
    /// \param[in] max_terms The term count.
    void SetMaxTerms(const unsigned int max_terms = 5);

    ///
    /// \brief Returns the format used for writing clustering results.
    /// \returns \c OutputFormat::XML for XML format, or \c OutputFormat::JSON for JSON format.
    OutputFormat GetOutputFormat();

    ///
    /// \brief Sets the file format for clustering results.
    /// \param[in] format Either \c OutputFormat::XML for XML format, or
    /// \c OutputFormat::JSON for JSON format.
    void SetOutputFormat(const OutputFormat format = JSON);

    ///
    /// \brief Returns the tolerance for the NMF subproblems solved by HierNMF2.
    /// \return The tolerance as a double-precision value.
    double GetHierNmf2Tolerance();

    ///
    /// \brief Sets the tolerance for the NMF subproblems solved by HierNMF2.
    /// \param[in] tol The tolerance value, a double precision value on (0.0, 1.0).
    void SetHierNmf2Tolerance(const double tol = 0.0001);

    ///
    /// \brief Performs hierarchical clustering for the loaded matrix.
    /// \param[in] num_clusters The number of clusters (leaf nodes) to generate.
    ///
    /// This function runs the HierNMF2 algorithm on the loaded matrix.  Two result files
    /// are written to the output directory, one containing the cluster labels for each
    /// document.  A value of -1 in this file represents an outlier, which is a document
    /// that was not assigned to a cluster.  The other output file contains information
    /// for each node in the factorization tree.
    void HierNmf2(const unsigned int num_clusters);

    ///
    /// \brief Performs hierarchical and flat clustering for the loaded matrix.
    /// \param[in] num_clusters The number of clusters to generate.
    ///
    /// This function performs the same actions as HierNmf2, but it also generates a flat
    /// clustering result, in addition the the hierarchical clustering result.  Two additional
    /// result files are written to the output directory, one for the flat clustering assignments,
    /// and anther for the flat clustering nodes.
    void HierNmf2WithFlat(const unsigned int num_clusters);

    //@}

} // namespace smallk
<commit_msg>updated version string<commit_after>///
/// \file smallk.hpp
///
/// \brief The smallk API header file.
///
/// Copyright 2014 Georgia Institute of Technology
///
/// 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.

#pragma once

#include <string>
#include <vector>

#define SMALLK_MAJOR_VERSION 1
#define SMALLK_MINOR_VERSION 6
#define SMALLK_PATCH_LEVEL   2

namespace smallk
{
    ///
    /// The NMF algorithms supported by this API.
    ///
    enum Algorithm
    {
        MU,      ///< Multiplicative Updating, Lee & Seung
        BPP,     ///< Block Principal Pivoting, Kim and Park
        HALS,    ///< Hierarchical Alternating Least Squares, Cichocki & Pan
        RANK2    ///< Rank2, Kuang and Park
    };

    ///
    /// The output file formats supported by the clustering code.
    ///
    enum OutputFormat
    {
        XML,  ///< Extensible Markup Language
        JSON  ///< JavaScript Object Notation
    };

    /// \name Initialization and Cleanup
    //@{
    ///
    /// \brief Perform initialization - call this function first.
    ///
    /// Simply pass \c argc and \c argv from \c main to this function.
    ///
    /// \param[in] argc The number of command-line arguments.
    /// \param[in] argv The array of command-line argument strings.
    void Initialize(int& argc, char**& argv);

    ///
    /// \brief Determine whether the library has been initialized.
    /// \return A boolean indicating the initialization status.
    bool IsInitialized();

    ///
    /// \brief Perform cleanup - call this function last.
    void Finalize();
    //@}

    /// \name Versioning
    //@{
    ///
    /// \brief Returns the API major version.
    /// \return The major version number as an \c unsigned \c int.
    unsigned int GetMajorVersion();

    /// \brief Returns the API minor version.
    /// \return The minor version number as an \c unsigned \c int.
    unsigned int GetMinorVersion();

    /// \brief Returns the API patch level.
    /// \return The patch level as an \c unsigned \c int.
    unsigned int GetPatchLevel();

    /// \brief Returns the API version string.
    /// \return The version string formatted as \c major_version.minor_version.patch_level.
    std::string GetVersionString();
    //@}

    /// \name Common Functions
    //@{
    ///
    /// \brief Returns the precision with which output files will be written.
    /// \return The number of digits after the decimal point for elements of matrices \c W and \c H.
    unsigned int GetOutputPrecision();

    ///
    /// \brief Sets the precision with which output files will be written.
    /// \param[in] num_digits The desired number of digits after the decimal point.
    void SetOutputPrecision(const unsigned int num_digits = 6);

    ///
    /// \brief Returns the tolerance value used to terminate iterative NMF algorithms.
    /// \return The tolerance as a double-precision floating point number.
    ///
    /// The NMF algorithms used by smallk are iterative.  At each iteration, a metric
    /// is computed that estimates the progress made towards a solution.  The metrics
    /// are designed to decrease as the computation progresses.  The 'tolerance' parameter
    /// is the cutoff value for this metric, meaning that whenever the metric decreases
    /// to this value the iterations are terminated and the solution is said to have converged.
    /// There is a tradeoff between the maximum number of iterations and the tolerance.
    /// Smaller values of the tolerance generally require more iterations.
    double GetNmfTolerance();

    ///
    /// \brief Sets the cutoff tolerance for NMF iterations.
    /// \param[in] tol The tolerance value.
    void SetNmfTolerance(const double tol = 0.005);

    ///
    /// \brief Returns the maximum number of iterations allowed for either NMF or clustering.
    /// \return The iteration count as an unsigned integer.
    unsigned int GetMaxIter();

    ///
    /// \brief Sets the upper limit to the number of iterations for NMF and clustering.
    /// \param[in] max_iterations The maximum number of iterations to perform.
    void SetMaxIter(const unsigned int max_iterations = 5000);

    ///
    /// \brief Returns the minimum number of iterations performed by either the NMF or clustering code.
    /// \return The iteration count as an unsigned integer.
    unsigned int GetMinIter();

    ///
    /// \brief Sets the minimum number of iterations to be performed by either the NMF or clustering code.
    /// \param[in] min_iterations The minimum number of iterations to perform.
    void SetMinIter(const unsigned int min_iterations = 5);

    ///
    /// \brief Returns the maximum number of threads used for either the NMF or clustering computations.
    /// \return The thread count as an unsigned integer.
    unsigned int GetMaxThreads();

    ///
    /// \brief Sets an upper limit to the number of threads used by either the NMF or clustering code.
    /// \param[in] max_threads The maximum number of threads to use.
    ///
    /// The smallk code is multithreaded for improved performance.  The default upper limit
    /// to the number of threads used by the code is determined by the hardware's capabilities.
    /// Use this function to override this limit and restrict the thread count to a smaller range.
    /// Allowable values for max_threads are in the interval [1, hardware_max_threads].
    void SetMaxThreads(const unsigned int max_threads);

    ///
    /// \brief Sets all params to default values and clears any loaded matrices.
    void Reset();

    ///
    /// \brief Seed the random number generator with the specified value.
    /// \param[in] seed An integer seed value.
    void SeedRNG(const int seed);

    ///
    /// \brief Load the matrix to be factored from a file.
    /// \param[in] filepath The absolute or relative path to a matrix file.
    ///
    /// The smallk code can read matrix files in either CSV (comma separated value)
    /// or MTX (MatrixMarket) format.  CSV files are assumed to contain dense
    /// matrices, i.e. the CSV files must contain an entry for each matrix element.
    /// MTX files are assumed to contain sparse matrices only.
    void LoadMatrix(const std::string& filepath);

    ///
    /// \brief Load the dense matrix to be factored from a buffer.
    /// \param[in] buffer A pointer to the buffer containing the input matrix.
    /// \param[in] ldim The leading dimension of the input matrix buffer.
    /// \param[in] height The height of the input matrix.
    /// \param[in] width The width of the input matrixe.
    ///
    /// The smallk code can read dense matrix files from a pointer to a buffer.
    /// This can be used for passing in a matrix generated in python.
    void LoadMatrix(const double *buffer,
                    const unsigned int ldim,
                    const unsigned int height,
                    const unsigned int width);
    ///
    /// \brief Load the sparse matrix to be factored from a buffer.
    /// \param[in] height The height of the input matrix.
    /// \param[in] width The width of the input matrixe.
    /// \param[in] nz The number of non-zero entries in the matrix.
    /// \param[in] data A reference to the vector containing the non-zero input data.
    /// \param[in] row_indices A reference to the row_indicies vector.
    /// \param[in] col_offsets A reference to the col_offsets vector.
    ///
    /// The smallk code can read dense matrix files from a pointer to a buffer.
    /// This can be used for passing in a matrix generated in python.
    void LoadMatrix(const unsigned int height,
                    const unsigned int width,
                    const unsigned int nz,
                    const std::vector<double>& data,
                    const std::vector<unsigned int>& row_indices,
                    const std::vector<unsigned int>& col_offsets);

    ///
    /// \brief Returns whether a CSV or MTX file has been successfully loaded.
    /// \return A boolean indicating the presence or absence of a loaded matrix.
    bool IsMatrixLoaded();

    ///
    /// \brief Returns the output directory where result files will be written.
    /// \return A string representing the output directory.
    std::string GetOutputDir();

    ///
    /// \brief Sets the directory into which result files will be written.
    /// \param[in] outdir The absolute or relative path to an output directory.
    ///
    /// The otuput directory must exist - the smallk code will not create it.
    void SetOutputDir(const std::string& outdir);

    //@}

    /// \name NMF
    //@{
    ///
    /// \brief Runs the selected NMF algorithm on the loaded matrix.
    /// \param[in] k The width of matrix W or the height of matrix H.
    /// \param[in] algorithm The desired NMF algorithm.
    /// \param[in] initfile_w A CSV file containing initial values for \c m x \c k matrix W.
    /// \param[in] initfile_h A CSV file containing initial values for \c k x \c n matrix H.
    /// This function performs the factorization \c A \c ~ \c W \c H, where
    /// matrix A is \c m x \c n, matrix W is \c m x \c k, and matrix H is
    /// \c k x \c n.  Matrix A must have already been loaded by a prior
    /// call to \c LoadMatrix.
    void Nmf(const unsigned int k,
             const Algorithm algorithm = BPP,
             const std::string& initfile_w = std::string(""),
             const std::string& initfile_h = std::string(""));

    ///
    /// \brief Returns a pointer to the buffer containing the NMF result matrix W.
    /// \param[out] ldim The leading dimension of the W-buffer.
    /// \param[out] height The height of the W matrix.
    /// \param[out] width The width of the W matrix.
    const double* LockedBufferW(unsigned int& ldim,
                                unsigned int& height,
                                unsigned int& width);

    ///
    /// \brief Returns a pointer to the buffer containing the NMF result matrix H.
    /// \param[out] ldim The leading dimension of the H-buffer.
    /// \param[out] height The height of the H matrix.
    /// \param[out] width The width of the H matrix.
    const double* LockedBufferH(unsigned int& ldim,
                                unsigned int& height,
                                unsigned int& width);

    //@}

    /// \name Clustering
    //{@
    ///
    /// \brief Load the file containing the dictionary strings.
    /// \param[in] filepath The absolute or relative path to the dictionary file.
    /// Each row of the term-frequency matrix represents a 'term' in the dictionary.
    /// The dictionary file is the collection of all such terms, one per line.
    /// A 'term' can consist of multiple words.  The smallk code considers each individual
    /// line in the file a separate term.
    ///
    void LoadDictionary(const std::string& filepath);

    ///
    /// \brief Load the file containing the dictionary strings.
    /// \param[in] terms The vector containing the dictionary terms.
    ///
    void LoadDictionary(const std::vector<std::string>& terms);

    ///
    /// \brief Reuturns the maximum number of terms computed per node during clustering.
    /// \return The term count as an unsigned int.
    unsigned int GetMaxTerms();

    ///
    /// \brief Set the maximum number of terms to compute per node during clustering.
    /// \param[in] max_terms The term count.
    void SetMaxTerms(const unsigned int max_terms = 5);

    ///
    /// \brief Returns the format used for writing clustering results.
    /// \returns \c OutputFormat::XML for XML format, or \c OutputFormat::JSON for JSON format.
    OutputFormat GetOutputFormat();

    ///
    /// \brief Sets the file format for clustering results.
    /// \param[in] format Either \c OutputFormat::XML for XML format, or
    /// \c OutputFormat::JSON for JSON format.
    void SetOutputFormat(const OutputFormat format = JSON);

    ///
    /// \brief Returns the tolerance for the NMF subproblems solved by HierNMF2.
    /// \return The tolerance as a double-precision value.
    double GetHierNmf2Tolerance();

    ///
    /// \brief Sets the tolerance for the NMF subproblems solved by HierNMF2.
    /// \param[in] tol The tolerance value, a double precision value on (0.0, 1.0).
    void SetHierNmf2Tolerance(const double tol = 0.0001);

    ///
    /// \brief Performs hierarchical clustering for the loaded matrix.
    /// \param[in] num_clusters The number of clusters (leaf nodes) to generate.
    ///
    /// This function runs the HierNMF2 algorithm on the loaded matrix.  Two result files
    /// are written to the output directory, one containing the cluster labels for each
    /// document.  A value of -1 in this file represents an outlier, which is a document
    /// that was not assigned to a cluster.  The other output file contains information
    /// for each node in the factorization tree.
    void HierNmf2(const unsigned int num_clusters);

    ///
    /// \brief Performs hierarchical and flat clustering for the loaded matrix.
    /// \param[in] num_clusters The number of clusters to generate.
    ///
    /// This function performs the same actions as HierNmf2, but it also generates a flat
    /// clustering result, in addition the the hierarchical clustering result.  Two additional
    /// result files are written to the output directory, one for the flat clustering assignments,
    /// and anther for the flat clustering nodes.
    void HierNmf2WithFlat(const unsigned int num_clusters);

    //@}

} // namespace smallk
<|endoftext|>


<commit_before><commit_msg>Print correct bitness of required Render Doc DLL<commit_after><|endoftext|>


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

#pragma once

typedef signed char        int8_t;
typedef unsigned char      uint8_t;
typedef short              int16_t;
typedef unsigned short     uint16_t;
typedef int                int32_t;
typedef unsigned int       uint32_t;
typedef unsigned           uint_t;
#if defined(_WIN32) || defined(__APPLE__) || defined(__arm__) || defined(__ppc__)
typedef long long          int64_t;
typedef unsigned long long uint64_t;
typedef __INTMAX_TYPE__    intmax_t;
typedef __UINTMAX_TYPE__   uintmax_t;
#else
typedef long               int64_t;
typedef unsigned long      uint64_t;
typedef int64_t            intmax_t;
typedef uint64_t           uintmax_t;
#endif

namespace ox {

typedef uint32_t Error;

}

#if defined(_LP64) || defined(__ppc64__) || defined(__aarch64__)
typedef unsigned long size_t;
#elif defined(_WIN64)
typedef uint64_t size_t;
#elif defined(_LP32) || defined(__ppc__) || defined(_WIN32) || defined(__arm__)
typedef uint32_t size_t;
#else
#error size_t undefined
#endif
<commit_msg>Add static_assert size checks to types.hpp<commit_after>/*
 * Copyright 2015 - 2018 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

typedef signed char        int8_t;
typedef unsigned char      uint8_t;
typedef short              int16_t;
typedef unsigned short     uint16_t;
typedef int                int32_t;
typedef unsigned int       uint32_t;
typedef unsigned           uint_t;
#if defined(_WIN32) || defined(__APPLE__) || defined(__arm__) || defined(__ppc__)
typedef long long          int64_t;
typedef unsigned long long uint64_t;
typedef __INTMAX_TYPE__    intmax_t;
typedef __UINTMAX_TYPE__   uintmax_t;
#else
typedef long               int64_t;
typedef unsigned long      uint64_t;
typedef int64_t            intmax_t;
typedef uint64_t           uintmax_t;
#endif

static_assert(sizeof(int8_t)  == 1, "int8_t is wrong size");
static_assert(sizeof(int16_t) == 2, "int16_t is wrong size");
static_assert(sizeof(int32_t) == 4, "int32_t is wrong size");
static_assert(sizeof(int64_t) == 8, "int64_t is wrong size");

static_assert(sizeof(uint8_t)  == 1, "uint8_t is wrong size");
static_assert(sizeof(uint16_t) == 2, "uint16_t is wrong size");
static_assert(sizeof(uint32_t) == 4, "uint32_t is wrong size");
static_assert(sizeof(uint64_t) == 8, "uint64_t is wrong size");

namespace ox {

typedef uint32_t Error;

}

#if defined(_LP64) || defined(__ppc64__) || defined(__aarch64__)
typedef unsigned long size_t;
#elif defined(_WIN64)
typedef uint64_t size_t;
#elif defined(_LP32) || defined(__ppc__) || defined(_WIN32) || defined(__arm__)
typedef uint32_t size_t;
#else
#error size_t undefined
#endif
<|endoftext|>


<commit_before>//  Boost wide_test.cpp  -----------------------------------------------------//
//  Copyright Beman Dawes 2005
//  Use, modification, and distribution is subject to the Boost Software
//  License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//  See library home page at http://www.boost.org/libs/filesystem

// Boost
#include <boost/version.hpp> // To check whether which version API is needed
#include <boost/config/warning_disable.hpp>

//  See deprecated_test for tests of deprecated features
#ifndef BOOST_FILESYSTEM_NO_DEPRECATED
# define BOOST_FILESYSTEM_NO_DEPRECATED
#endif
#ifndef BOOST_SYSTEM_NO_DEPRECATED
# define BOOST_SYSTEM_NO_DEPRECATED
#endif

#include <boost/filesystem/config.hpp>

#if defined(BOOST_VERSION) && BOOST_VERSION >= 104400
# ifdef BOOST_FILESYSTEM2_NARROW_ONLY
#   error This compiler or standard library does not support wide-character strings or paths
# endif
#else // BOOST_VERSION
# ifdef BOOST_FILESYSTEM_NARROW_ONLY
#   error This compiler or standard library does not support wide-character strings or paths
# endif
#endif // BOOST_VERSION

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/scoped_array.hpp>
#include <boost/detail/lightweight_test.hpp>

#if defined(BOOST_VERSION) && BOOST_VERSION >= 104400
#  include <boost/filesystem/detail/utf8_codecvt_facet.hpp>
#else // BOOST_VERSION
#  include "utf8_codecvt_facet.hpp"
#endif // BOOST_VERSION

namespace fs = boost::filesystem;

// STL
#include <iostream>
#include <iomanip>
#include <ios>
#include <string>
#include <cerrno>

#include "lpath.hpp"

namespace {

  bool cleanup = true;

  template< class Path >
  void create_file( const Path & ph, const std::string & contents )
  {
    // TODO: why missing symbol error on Darwin
# ifndef __APPLE__
    fs::ofstream f( ph );
# else
    std::ofstream f( ph.external_file_string().c_str() );
# endif
    if ( !f )
      throw fs::basic_filesystem_error<Path>( "wide_test create_file",
                                              ph,
#if defined(BOOST_VERSION) && BOOST_VERSION >= 104400
        boost::system::error_code( errno, boost::system::generic_category() ) );
#else // BOOST_VERSION
        boost::system::error_code( errno, boost::system::errno_ecat ) );
#endif // BOOST_VERSION
    if ( !contents.empty() ) f << contents;
  }

  template< class Path >
  void test( const Path & dir, const Path & file, const Path & dot )
  {
    Path tmp;
    tmp = file;
    BOOST_TEST( tmp == file );
    tmp = file.string();
    BOOST_TEST( tmp == file );
    tmp = file.string().c_str();
    BOOST_TEST( tmp == file );
    fs::initial_path<Path>();
    fs::current_path<Path>();
    fs::remove( dir / file );
    fs::remove( dir );
    BOOST_TEST( !fs::exists( dir / file ) );
    BOOST_TEST( !fs::exists( dir ) );
    BOOST_TEST( fs::create_directory( dir ) );
    BOOST_TEST( fs::exists( dir ) );
    BOOST_TEST( fs::is_directory( dir ) );
    BOOST_TEST( fs::is_empty( dir ) );
    create_file( dir / file, "wide_test file contents" );
    BOOST_TEST( fs::exists( dir / file ) );
    BOOST_TEST( !fs::is_directory( dir / file ) );
    BOOST_TEST( !fs::is_empty( dir / file ) );
    BOOST_TEST( fs::file_size( dir / file ) == 23 || fs::file_size( dir / file ) == 24 );
    BOOST_TEST( fs::equivalent( dir / file, dot / dir / file ) );
    BOOST_TEST( fs::last_write_time( dir / file ) );
    typedef fs::basic_directory_iterator<Path> it_t;
    int count(0);
    for ( it_t it( dir ); it != it_t(); ++it )
      {
        BOOST_TEST( it->path() == dir / file );
        BOOST_TEST( !fs::is_empty( it->path() ) );
        ++count;
      }
    BOOST_TEST( count == 1 );
    if ( cleanup )
      {
        fs::remove( dir / file );
        fs::remove( dir );
      }
  }

  // test boost::detail::utf8_codecvt_facet - even though it is not used by
  // Boost.Filesystem on Windows, early detection of problems is worthwhile.
  std::string to_external( const std::wstring & src )
  {
    fs::detail::utf8_codecvt_facet convertor;
    std::size_t work_size( convertor.max_length() * (src.size()+1) );
    boost::scoped_array<char> work( new char[ work_size ] );
    std::mbstate_t state;
    const wchar_t * from_next;
    char * to_next;
    if ( convertor.out(
      state, src.c_str(), src.c_str()+src.size(), from_next, work.get(),
      work.get()+work_size, to_next ) != std::codecvt_base::ok )
      boost::throw_exception( std::runtime_error("to_external conversion error") );
    *to_next = '\0';
    return std::string( work.get() );
  }

} // unnamed namespace

//  main  --------------------------------------------------------------------//

int main( int argc, char * /*argv*/[] )
{

  if ( argc > 1 ) cleanup = false;

  // So that tests are run with known encoding, use Boost UTF-8 codecvt
  std::locale global_loc = std::locale();
  std::locale loc( global_loc, new fs::detail::utf8_codecvt_facet );
  fs::wpath_traits::imbue( loc );

  std::string s( to_external( L"\x2780" ) );
  for (std::size_t i = 0; i < s.size(); ++i )
    std::cout << std::hex << int( static_cast<unsigned char>(s[i]) ) << " ";
  std::cout << std::dec << std::endl;
  BOOST_TEST( to_external( L"\x2780" ).size() == 3 );
  BOOST_TEST( to_external( L"\x2780" ) == "\xE2\x9E\x80" );

  // test fs::path
  std::cout << "begin path test..." << std::endl;
  test( fs::path( "foo" ), fs::path( "bar" ), fs::path( "." ) );
  std::cout << "complete\n\n";

  // test fs::wpath
  //  x2780 is circled 1 against white background == e2 9e 80 in UTF-8
  //  x2781 is circled 2 against white background == e2 9e 81 in UTF-8
  std::cout << "begin wpath test..." << std::endl;
  test( fs::wpath( L"\x2780" ), fs::wpath( L"\x2781" ), fs::wpath( L"." ) );
  std::cout << "complete\n\n";

  // test user supplied basic_path
  const long dir[] = { 'b', 'o', 'o', 0 };
  const long file[] = { 'f', 'a', 'r', 0 };
  const long dot[] = { '.', 0 };
  std::cout << "begin lpath test..." << std::endl;
  test( ::user::lpath( dir ), ::user::lpath( file ), ::user::lpath( dot ) );
  std::cout << "complete\n\n";

  return ::boost::report_errors();
}
<commit_msg>[Test-Boost] Fixed the Boost.Filesystem compilation error for version lower than 1.44.<commit_after>//  Boost wide_test.cpp  -----------------------------------------------------//
//  Copyright Beman Dawes 2005
//  Use, modification, and distribution is subject to the Boost Software
//  License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//  See library home page at http://www.boost.org/libs/filesystem

// Boost
#include <boost/version.hpp> // To check whether which version API is needed
#include <boost/config/warning_disable.hpp>

//  See deprecated_test for tests of deprecated features
#ifndef BOOST_FILESYSTEM_NO_DEPRECATED
# define BOOST_FILESYSTEM_NO_DEPRECATED
#endif
#if defined(BOOST_VERSION) && BOOST_VERSION >= 104400
#ifndef BOOST_SYSTEM_NO_DEPRECATED
# define BOOST_SYSTEM_NO_DEPRECATED
#endif // BOOST_SYSTEM_NO_DEPRECATED
#endif // BOOST_VERSION

#include <boost/filesystem/config.hpp>

#if defined(BOOST_VERSION) && BOOST_VERSION >= 104400
# ifdef BOOST_FILESYSTEM2_NARROW_ONLY
#   error This compiler or standard library does not support wide-character strings or paths
# endif
#else // BOOST_VERSION
# ifdef BOOST_FILESYSTEM_NARROW_ONLY
#   error This compiler or standard library does not support wide-character strings or paths
# endif
#endif // BOOST_VERSION

#include <boost/filesystem/operations.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/scoped_array.hpp>
#include <boost/detail/lightweight_test.hpp>

#if defined(BOOST_VERSION) && BOOST_VERSION >= 104400
#  include <boost/filesystem/detail/utf8_codecvt_facet.hpp>
#else // BOOST_VERSION
#  include "utf8_codecvt_facet.hpp"
#endif // BOOST_VERSION

namespace fs = boost::filesystem;

// STL
#include <iostream>
#include <iomanip>
#include <ios>
#include <string>
#include <cerrno>

#include "lpath.hpp"

namespace {

  bool cleanup = true;

  template< class Path >
  void create_file( const Path & ph, const std::string & contents )
  {
    // TODO: why missing symbol error on Darwin
# ifndef __APPLE__
    fs::ofstream f( ph );
# else
    std::ofstream f( ph.external_file_string().c_str() );
# endif
    if ( !f )
      throw fs::basic_filesystem_error<Path>( "wide_test create_file",
                                              ph,
#if defined(BOOST_VERSION) && BOOST_VERSION >= 104400
        boost::system::error_code( errno, boost::system::generic_category() ) );
#else // BOOST_VERSION
        boost::system::error_code( errno, boost::system::errno_ecat ) );
#endif // BOOST_VERSION
    if ( !contents.empty() ) f << contents;
  }

  template< class Path >
  void test( const Path & dir, const Path & file, const Path & dot )
  {
    Path tmp;
    tmp = file;
    BOOST_TEST( tmp == file );
    tmp = file.string();
    BOOST_TEST( tmp == file );
    tmp = file.string().c_str();
    BOOST_TEST( tmp == file );
    fs::initial_path<Path>();
    fs::current_path<Path>();
    fs::remove( dir / file );
    fs::remove( dir );
    BOOST_TEST( !fs::exists( dir / file ) );
    BOOST_TEST( !fs::exists( dir ) );
    BOOST_TEST( fs::create_directory( dir ) );
    BOOST_TEST( fs::exists( dir ) );
    BOOST_TEST( fs::is_directory( dir ) );
    BOOST_TEST( fs::is_empty( dir ) );
    create_file( dir / file, "wide_test file contents" );
    BOOST_TEST( fs::exists( dir / file ) );
    BOOST_TEST( !fs::is_directory( dir / file ) );
    BOOST_TEST( !fs::is_empty( dir / file ) );
    BOOST_TEST( fs::file_size( dir / file ) == 23 || fs::file_size( dir / file ) == 24 );
    BOOST_TEST( fs::equivalent( dir / file, dot / dir / file ) );
    BOOST_TEST( fs::last_write_time( dir / file ) );
    typedef fs::basic_directory_iterator<Path> it_t;
    int count(0);
    for ( it_t it( dir ); it != it_t(); ++it )
      {
        BOOST_TEST( it->path() == dir / file );
        BOOST_TEST( !fs::is_empty( it->path() ) );
        ++count;
      }
    BOOST_TEST( count == 1 );
    if ( cleanup )
      {
        fs::remove( dir / file );
        fs::remove( dir );
      }
  }

  // test boost::detail::utf8_codecvt_facet - even though it is not used by
  // Boost.Filesystem on Windows, early detection of problems is worthwhile.
  std::string to_external( const std::wstring & src )
  {
    fs::detail::utf8_codecvt_facet convertor;
    std::size_t work_size( convertor.max_length() * (src.size()+1) );
    boost::scoped_array<char> work( new char[ work_size ] );
    std::mbstate_t state;
    const wchar_t * from_next;
    char * to_next;
    if ( convertor.out(
      state, src.c_str(), src.c_str()+src.size(), from_next, work.get(),
      work.get()+work_size, to_next ) != std::codecvt_base::ok )
      boost::throw_exception( std::runtime_error("to_external conversion error") );
    *to_next = '\0';
    return std::string( work.get() );
  }

} // unnamed namespace

//  main  --------------------------------------------------------------------//

int main( int argc, char * /*argv*/[] )
{

  if ( argc > 1 ) cleanup = false;

  // So that tests are run with known encoding, use Boost UTF-8 codecvt
  std::locale global_loc = std::locale();
  std::locale loc( global_loc, new fs::detail::utf8_codecvt_facet );
  fs::wpath_traits::imbue( loc );

  std::string s( to_external( L"\x2780" ) );
  for (std::size_t i = 0; i < s.size(); ++i )
    std::cout << std::hex << int( static_cast<unsigned char>(s[i]) ) << " ";
  std::cout << std::dec << std::endl;
  BOOST_TEST( to_external( L"\x2780" ).size() == 3 );
  BOOST_TEST( to_external( L"\x2780" ) == "\xE2\x9E\x80" );

  // test fs::path
  std::cout << "begin path test..." << std::endl;
  test( fs::path( "foo" ), fs::path( "bar" ), fs::path( "." ) );
  std::cout << "complete\n\n";

  // test fs::wpath
  //  x2780 is circled 1 against white background == e2 9e 80 in UTF-8
  //  x2781 is circled 2 against white background == e2 9e 81 in UTF-8
  std::cout << "begin wpath test..." << std::endl;
  test( fs::wpath( L"\x2780" ), fs::wpath( L"\x2781" ), fs::wpath( L"." ) );
  std::cout << "complete\n\n";

  // test user supplied basic_path
  const long dir[] = { 'b', 'o', 'o', 0 };
  const long file[] = { 'f', 'a', 'r', 0 };
  const long dot[] = { '.', 0 };
  std::cout << "begin lpath test..." << std::endl;
  test( ::user::lpath( dir ), ::user::lpath( file ), ::user::lpath( dot ) );
  std::cout << "complete\n\n";

  return ::boost::report_errors();
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2010 Tommi Maekitalo
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "worker.h"
#include "serverimpl.h"
#include <cxxtools/log.h>
#include "socket.h"

log_define("cxxtools.http.worker")

namespace cxxtools
{
namespace http
{

void Worker::run()
{
    log_info("new thread running");
    while (!_server.isTerminating() && _server._queue.numWaiting() < _server.minThreads())
    {
        Socket* socket = _server._queue.get();

        if (_server.isTerminating())
        {
            log_debug("server is terminating - quit thread");
            _server._queue.put(socket);
            break;
        }

        if (_server._queue.numWaiting() == 0)
            _server.noWaitingThreads();

        try
        {
            if (!socket->hasAccepted())
            {
                // do blocking accept
                socket->accept();
                log_debug("connection accepted from " << socket->getPeerAddr());

                if (_server.isTerminating())
                {
                    log_debug("server is terminating - quit thread");
                    _server._queue.put(socket);
                    break;
                }

                // new connection arrived - create new accept socket
                _server._queue.put(new Socket(*socket));
            }
            else if (socket->isConnected())
            {
                log_debug("process available input");
                socket->onInput(socket->buffer());
            }
            else
            {
                log_debug("socket is not connected any more; delete " << static_cast<void*>(socket));
                delete socket;
            }

            connect(socket->buffer().inputReady, socket->inputSlot);

            while (socket->wait(_server.idleTimeout()) && socket->isConnected())
                ;

            if (socket->isConnected())
            {
                log_debug("timeout processing socket");
                disconnect(socket->buffer().inputReady, socket->inputSlot);
                _server.addIdleSocket(socket);
            }
            else if (_server.isTerminating())
            {
                _server._queue.put(socket);
            }
            else
            {
                log_debug("socket is not connected any more; delete " << static_cast<void*>(socket));
                delete socket;
            }
        }
        catch (const std::exception& e)
        {
            log_debug("error occured in device: " << e.what() << "; delete " << static_cast<void*>(socket));
            delete socket;
        }
    }

    log_info("thread terminated");
    _server.threadTerminated(this);
}

}
}
<commit_msg>bugfix: do not use deleted http socket any more<commit_after>/*
 * Copyright (C) 2010 Tommi Maekitalo
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * As a special exception, you may use this file as part of a free
 * software library without restriction. Specifically, if other files
 * instantiate templates or use macros or inline functions from this
 * file, or you compile this file and link it with other files to
 * produce an executable, this file does not by itself cause the
 * resulting executable to be covered by the GNU General Public
 * License. This exception does not however invalidate any other
 * reasons why the executable file might be covered by the GNU Library
 * General Public License.
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "worker.h"
#include "serverimpl.h"
#include <cxxtools/log.h>
#include "socket.h"

log_define("cxxtools.http.worker")

namespace cxxtools
{
namespace http
{

void Worker::run()
{
    log_info("new thread running");
    while (!_server.isTerminating() && _server._queue.numWaiting() < _server.minThreads())
    {
        Socket* socket = _server._queue.get();

        if (_server.isTerminating())
        {
            log_debug("server is terminating - quit thread");
            _server._queue.put(socket);
            break;
        }

        if (_server._queue.numWaiting() == 0)
            _server.noWaitingThreads();

        try
        {
            if (!socket->hasAccepted())
            {
                // do blocking accept
                socket->accept();
                log_debug("connection accepted from " << socket->getPeerAddr());

                if (_server.isTerminating())
                {
                    log_debug("server is terminating - quit thread");
                    _server._queue.put(socket);
                    break;
                }

                // new connection arrived - create new accept socket
                _server._queue.put(new Socket(*socket));
            }
            else if (socket->isConnected())
            {
                log_debug("process available input");
                socket->onInput(socket->buffer());
            }
            else
            {
                log_debug("socket is not connected any more; delete " << static_cast<void*>(socket));
                delete socket;
                continue;
            }

            connect(socket->buffer().inputReady, socket->inputSlot);

            while (socket->wait(_server.idleTimeout()) && socket->isConnected())
                ;

            if (socket->isConnected())
            {
                log_debug("timeout processing socket");
                disconnect(socket->buffer().inputReady, socket->inputSlot);
                _server.addIdleSocket(socket);
            }
            else if (_server.isTerminating())
            {
                _server._queue.put(socket);
            }
            else
            {
                log_debug("socket is not connected any more; delete " << static_cast<void*>(socket));
                delete socket;
            }
        }
        catch (const std::exception& e)
        {
            log_debug("error occured in device: " << e.what() << "; delete " << static_cast<void*>(socket));
            delete socket;
        }
    }

    log_info("thread terminated");
    _server.threadTerminated(this);
}

}
}
<|endoftext|>


<commit_before>//============================================================================
// Name        : SmartBreakerServer.cpp
// Author      : Bingyu
// Version     :
// Copyright   : ZEin 2017
// Description :
//============================================================================

#include <muduo/base/Mutex.h>
#include <muduo/base/Logging.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/EventLoopThread.h>
#include <muduo/net/InetAddress.h>
#include <muduo/net/inspect/Inspector.h>

#include <boost/bind.hpp>
#include <boost/random.hpp>
#include <boost/random/seed_seq.hpp>

#include <string.h>
#include <unistd.h>

#include <iostream>

using namespace muduo;
using namespace muduo::net;

//using namespace std;

#include <ctime>

#include "gconf.h"
#include "commons.h"

#include "redisWrapper.h"
#include "servers.h"

namespace muduo
{
namespace inspect
{
int stringPrintf(string* out, const char* fmt, ...) __attribute__ ((format (printf, 2, 3)));
}
}

using muduo::inspect::stringPrintf;

boost::mt19937 gRng;

string GetOverview(HttpRequest::Method, const Inspector::ArgList&,
                   AgtServer *pAgt, HookServer *pHook)
{
	string result;

	result.reserve(1024);
	stringPrintf(&result, "Current active links:\n\n");
	stringPrintf(&result, "Agents: %5d / %d\n", pAgt->getNumConn(), gConf.agtCmax_);
	stringPrintf(&result, "Hooks:  %5d / %d\n", pHook->getNumConn(), gConf.hookCmax_);

    return result;
}

void SBSMain(void)
{
    unsigned tt[2] = { static_cast<unsigned int>(std::time(0)), 2323ul };

    boost::random::seed_seq ss(tt);
	gRng.seed(ss);

	EventLoop loop;
	EventLoopThread tIns, tQuery;
	Inspector ins(tIns.startLoop(), InetAddress(gConf.monPort_), "Inspector");

	hiredis::redisQuery qRedis(&loop, InetAddress(gConf.rds1Addr_, gConf.rds1Port_));
	qRedis.connect();

	hiredis::redisStore sRedis(tQuery.startLoop(), InetAddress(gConf.rds1Addr_, gConf.rds1Port_));
    sRedis.connect();

    HookServer hookSvr(&loop, InetAddress(static_cast<uint16_t>(gConf.hookPort_)),
                       gConf.hookCmax_, "TCPHook");
    hookSvr.start();

	// Start Agent Listener
    AgtServer agtServer(&loop, InetAddress(static_cast<uint16_t>(gConf.agtPort_)),
                      gConf.agtCmax_, "AgentServer", &sRedis, &qRedis, &hookSvr);
    agtServer.start();

	// Add inspector entrance

	ins.add("smbrk", "links",
            boost::bind(GetOverview, _1, _2, &agtServer, &hookSvr),
            "Active links overview");

	loop.loop();
}
<commit_msg>Minor changes<commit_after>//============================================================================
// Name        : SmartBreakerServer.cpp
// Author      : Bingyu
// Version     :
// Copyright   : ZEin 2017
// Description :
//============================================================================

#include <muduo/base/Mutex.h>
#include <muduo/base/Logging.h>
#include <muduo/net/EventLoop.h>
#include <muduo/net/EventLoopThread.h>
#include <muduo/net/InetAddress.h>
#include <muduo/net/inspect/Inspector.h>

#include <boost/bind.hpp>
#include <boost/random.hpp>
#include <boost/random/seed_seq.hpp>

#include <string.h>
#include <unistd.h>

#include <iostream>

using namespace muduo;
using namespace muduo::net;

//using namespace std;

#include <ctime>

#include "gconf.h"
#include "commons.h"

#include "redisWrapper.h"
#include "servers.h"

namespace muduo
{
namespace inspect
{
int stringPrintf(string* out, const char* fmt, ...) __attribute__ ((format (printf, 2, 3)));
}
}

using muduo::inspect::stringPrintf;

boost::mt19937 gRng;

string GetOverview(HttpRequest::Method, const Inspector::ArgList&,
                   AgtServer *pAgt, HookServer *pHook)
{
	string result;

	result.reserve(1024);
	stringPrintf(&result, "Current active links:\n\n");
	stringPrintf(&result, "Agents: %5d / %d\n", pAgt->getNumConn(), gConf.agtCmax_);
	stringPrintf(&result, "Hooks:  %5d / %d\n", pHook->getNumConn(), gConf.hookCmax_);

    return result;
}

void SBSMain(void)
{
    unsigned tt[2] = { static_cast<unsigned int>(std::time(0)), 2323ul };

    boost::random::seed_seq ss(tt);
	gRng.seed(ss);

	EventLoop loop;
	EventLoopThread tIns, tQuery;
	Inspector ins(tIns.startLoop(), InetAddress(gConf.monPort_), "Breaker Inspector");

	hiredis::redisQuery qRedis(&loop, InetAddress(gConf.rds1Addr_, gConf.rds1Port_));
	qRedis.connect();

	hiredis::redisStore sRedis(tQuery.startLoop(), InetAddress(gConf.rds1Addr_, gConf.rds1Port_));
    sRedis.connect();

    HookServer hookSvr(&loop, InetAddress(static_cast<uint16_t>(gConf.hookPort_)),
                       gConf.hookCmax_, "TCPHook");
    hookSvr.start();

	// Start Agent Listener
    AgtServer agtServer(&loop, InetAddress(static_cast<uint16_t>(gConf.agtPort_)),
                       gConf.agtCmax_, "AgentServer", &sRedis, &qRedis, &hookSvr);
    agtServer.start();

	// Add inspector entrance

	ins.add("smbrk", "links",
            boost::bind(GetOverview, _1, _2, &agtServer, &hookSvr),
            "print links overview");

	loop.loop();
}
<|endoftext|>


<commit_before>
#include <SpikeHwIndication.h>
#include <SpikeHwRequest.h>
#include "dmaManager.h"
#include "spikehw.h"
#include <iostream>
#include <functional>
#include <riscv/devices.h>

int verbose = 0;

class SpikeHwIndication : public SpikeHwIndicationWrapper
{
  sem_t sem;
public:
    uint32_t buf[16];

  void irqChanged( const uint8_t irqLevel, const uint8_t intrSources ) {
      fprintf(stderr, "irqLevel %d intr sources %x\n", irqLevel, intrSources);
    }
    virtual void resetDone() {
	fprintf(stderr, "reset done\n");
	sem_post(&sem);
    }
    virtual void status ( const uint8_t mmcm_locked, const uint8_t irq, const uint8_t intrSources ) {
	fprintf(stderr, "axi eth status mmcm_locked=%d irq=%d intr sources=%x\n", mmcm_locked, irq, intrSources);
	sem_post(&sem);
    }

    void wait() {
	sem_wait(&sem);
    }

    void readDone ( const uint32_t value ) {
	buf[0] = value;
	if (verbose) fprintf(stderr, "readDone value=%08x\n", value);
	sem_post(&sem);
    }

    void writeDone (  ) {
	if (verbose) fprintf(stderr, "writeDone\n");
	sem_post(&sem);
    }

    void readFlashDone ( const uint32_t value ) {
	buf[0] = value;
	if (verbose) fprintf(stderr, "readFlashDone value=%08x\n", value);
	sem_post(&sem);
    }

    void writeFlashDone (  ) {
	if (verbose) fprintf(stderr, "writeFlashDone\n");
	sem_post(&sem);
    }

    SpikeHwIndication(unsigned int id) : SpikeHwIndicationWrapper(id) {
      sem_init(&sem, 0, 0);
    }
};

SpikeHwRequestProxy *request;
SpikeHwIndication *indication;

SpikeHw::SpikeHw()
    : request(0), indication(0), dmaManager(0), didReset(false)
{
    request = new SpikeHwRequestProxy(IfcNames_SpikeHwRequestS2H);
    indication = new SpikeHwIndication(IfcNames_SpikeHwIndicationH2S);
    dmaManager = platformInit();
    request->setFlashParameters(50);
}

SpikeHw::~SpikeHw()
{
  //delete request;
  //delete indication;
  request = 0;
  indication = 0;
}

void SpikeHw::maybeReset()
{
    if (0)
    if (!didReset) {
	fprintf(stderr, "resetting flash\n");
	request->reset();
	indication->wait();
	//request->setParameters(50, 0);
	fprintf(stderr, "done resetting flash\n");
	didReset = true;
    }
}

void SpikeHw::status()
{
    request->status();
    indication->wait();
}

void SpikeHw::setupDma(uint32_t memfd)
{
    int memref = dmaManager->reference(memfd);
    request->setupDma(memref);
}

void SpikeHw::read(unsigned long offset, uint8_t *buf)
{
    maybeReset();

    if (verbose) fprintf(stderr, "SpikeHw::read offset=%lx\n", offset);
    request->read(offset);
    indication->wait();
    if (verbose) fprintf(stderr, "SpikeHw::read offset=%lx value=%x\n", offset, *(uint32_t *)indication->buf);
    memcpy(buf, indication->buf, 4);
}

void SpikeHw::write(unsigned long offset, const uint8_t *buf)
{
    maybeReset();

    if (1 || verbose) fprintf(stderr, "SpikeHw::write offset=%lx value=%x\n", offset, *(uint32_t *)buf);
    request->write(offset, *(uint32_t *)buf);
    indication->wait();
    request->status();
    indication->wait();
}

void SpikeHw::setFlashParameters(unsigned long cycles)
{
    request->setFlashParameters(cycles);
}

void SpikeHw::readFlash(unsigned long offset, uint8_t *buf)
{
    maybeReset();

    if (verbose) fprintf(stderr, "SpikeHw::readFlash offset=%lx\n", offset);
    request->readFlash(offset);
    indication->wait();
    if (verbose) fprintf(stderr, "SpikeHw::readFlash offset=%lx value=%x\n", offset, *(uint32_t *)indication->buf);
    memcpy(buf, indication->buf, 4);
}

void SpikeHw::writeFlash(unsigned long offset, const uint8_t *buf)
{
    maybeReset();

    if (1 || verbose) fprintf(stderr, "SpikeHw::writeFlash offset=%lx value=%x\n", offset, *(uint32_t *)buf);
    request->writeFlash(offset, *(uint32_t *)buf);
    indication->wait();
}

class spikehw_device_t : public abstract_device_t {
public:
  spikehw_device_t();
  bool load(reg_t addr, size_t len, uint8_t* bytes);
  bool store(reg_t addr, size_t len, const uint8_t* bytes);
  static abstract_device_t *make_device();
private:
  SpikeHw *spikeHw;
};

spikehw_device_t::spikehw_device_t()
{
  spikeHw = new SpikeHw();
}

bool spikehw_device_t::load(reg_t addr, size_t len, uint8_t* bytes)
{
    spikeHw->read(addr, bytes); // always reads 4 bytes
    return true;
}

bool spikehw_device_t::store(reg_t addr, size_t len, const uint8_t* bytes)
{
    spikeHw->write(addr, bytes);
    return true;
}

abstract_device_t *spikehw_device_t::make_device()
{
    std::cerr << "make_device called" << std::endl;
    return new spikehw_device_t();
}

REGISTER_DEVICE(spikehw, 0x42000000, spikehw_device_t::make_device);
<commit_msg>added devicetree device for bootstrapping<commit_after>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

#include <SpikeHwIndication.h>
#include <SpikeHwRequest.h>
#include "dmaManager.h"
#include "spikehw.h"
#include <iostream>
#include <functional>
#include <riscv/devices.h>

int verbose = 0;

class SpikeHwIndication : public SpikeHwIndicationWrapper
{
  sem_t sem;
public:
    uint32_t buf[16];

  void irqChanged( const uint8_t irqLevel, const uint8_t intrSources ) {
      fprintf(stderr, "irqLevel %d intr sources %x\n", irqLevel, intrSources);
    }
    virtual void resetDone() {
	fprintf(stderr, "reset done\n");
	sem_post(&sem);
    }
    virtual void status ( const uint8_t mmcm_locked, const uint8_t irq, const uint8_t intrSources ) {
	fprintf(stderr, "axi eth status mmcm_locked=%d irq=%d intr sources=%x\n", mmcm_locked, irq, intrSources);
	sem_post(&sem);
    }

    void wait() {
	sem_wait(&sem);
    }

    void readDone ( const uint32_t value ) {
	buf[0] = value;
	if (verbose) fprintf(stderr, "readDone value=%08x\n", value);
	sem_post(&sem);
    }

    void writeDone (  ) {
	if (verbose) fprintf(stderr, "writeDone\n");
	sem_post(&sem);
    }

    void readFlashDone ( const uint32_t value ) {
	buf[0] = value;
	if (verbose) fprintf(stderr, "readFlashDone value=%08x\n", value);
	sem_post(&sem);
    }

    void writeFlashDone (  ) {
	if (verbose) fprintf(stderr, "writeFlashDone\n");
	sem_post(&sem);
    }

    SpikeHwIndication(unsigned int id) : SpikeHwIndicationWrapper(id) {
      sem_init(&sem, 0, 0);
    }
};

SpikeHwRequestProxy *request;
SpikeHwIndication *indication;

SpikeHw::SpikeHw()
    : request(0), indication(0), dmaManager(0), didReset(false)
{
    request = new SpikeHwRequestProxy(IfcNames_SpikeHwRequestS2H);
    indication = new SpikeHwIndication(IfcNames_SpikeHwIndicationH2S);
    dmaManager = platformInit();
    request->setFlashParameters(50);
}

SpikeHw::~SpikeHw()
{
  //delete request;
  //delete indication;
  request = 0;
  indication = 0;
}

void SpikeHw::maybeReset()
{
    if (0)
    if (!didReset) {
	fprintf(stderr, "resetting flash\n");
	request->reset();
	indication->wait();
	//request->setParameters(50, 0);
	fprintf(stderr, "done resetting flash\n");
	didReset = true;
    }
}

void SpikeHw::status()
{
    request->status();
    indication->wait();
}

void SpikeHw::setupDma(uint32_t memfd)
{
    int memref = dmaManager->reference(memfd);
    request->setupDma(memref);
}

void SpikeHw::read(unsigned long offset, uint8_t *buf)
{
    maybeReset();

    if (verbose) fprintf(stderr, "SpikeHw::read offset=%lx\n", offset);
    request->read(offset);
    indication->wait();
    if (verbose) fprintf(stderr, "SpikeHw::read offset=%lx value=%x\n", offset, *(uint32_t *)indication->buf);
    memcpy(buf, indication->buf, 4);
}

void SpikeHw::write(unsigned long offset, const uint8_t *buf)
{
    maybeReset();

    if (1 || verbose) fprintf(stderr, "SpikeHw::write offset=%lx value=%x\n", offset, *(uint32_t *)buf);
    request->write(offset, *(uint32_t *)buf);
    indication->wait();
    request->status();
    indication->wait();
}

void SpikeHw::setFlashParameters(unsigned long cycles)
{
    request->setFlashParameters(cycles);
}

void SpikeHw::readFlash(unsigned long offset, uint8_t *buf)
{
    maybeReset();

    if (verbose) fprintf(stderr, "SpikeHw::readFlash offset=%lx\n", offset);
    request->readFlash(offset);
    indication->wait();
    if (verbose) fprintf(stderr, "SpikeHw::readFlash offset=%lx value=%x\n", offset, *(uint32_t *)indication->buf);
    memcpy(buf, indication->buf, 4);
}

void SpikeHw::writeFlash(unsigned long offset, const uint8_t *buf)
{
    maybeReset();

    if (1 || verbose) fprintf(stderr, "SpikeHw::writeFlash offset=%lx value=%x\n", offset, *(uint32_t *)buf);
    request->writeFlash(offset, *(uint32_t *)buf);
    indication->wait();
}

class spikehw_device_t : public abstract_device_t {
public:
  spikehw_device_t();
  bool load(reg_t addr, size_t len, uint8_t* bytes);
  bool store(reg_t addr, size_t len, const uint8_t* bytes);
  static abstract_device_t *make_device();
private:
  SpikeHw *spikeHw;
};

spikehw_device_t::spikehw_device_t()
{
  spikeHw = new SpikeHw();
}

bool spikehw_device_t::load(reg_t addr, size_t len, uint8_t* bytes)
{
    spikeHw->read(addr, bytes); // always reads 4 bytes
    return true;
}

bool spikehw_device_t::store(reg_t addr, size_t len, const uint8_t* bytes)
{
    spikeHw->write(addr, bytes);
    return true;
}

abstract_device_t *spikehw_device_t::make_device()
{
    std::cerr << "make_device called" << std::endl;
    return new spikehw_device_t();
}

class devicetree_device_t : public abstract_device_t {
public:
    devicetree_device_t();
    bool load(reg_t addr, size_t len, uint8_t* bytes);
    bool store(reg_t addr, size_t len, const uint8_t* bytes);
    static abstract_device_t *make_device();
private:
    const char *dtb;
    size_t dtbsz;
};

devicetree_device_t::devicetree_device_t()
{
    int fd = open("devicetree.dtb", O_RDONLY);
    if (fd > 0) {
	struct stat statbuf;
	int status = fstat(fd, &statbuf);
	fprintf(stderr, "fstat status %d size %ld\n", status, statbuf.st_size);
	if (status == 0) {
	    dtb = (const char *)mmap(0, statbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
	    dtbsz = statbuf.st_size;
	    fprintf(stderr, "mapped dtb at %p (%ld bytes)\n", dtb, dtbsz);
	}
	close(fd);
    } else {
	fprintf(stderr, "Could not open devicetree.dtb\n");
    }
}

bool devicetree_device_t::load(reg_t addr, size_t len, uint8_t* bytes)
{
    if (dtb && dtb != MAP_FAILED) {
	if ((addr < dtbsz) && (bytes != 0)) {
	    memcpy(bytes, dtb + addr, len);
	    return true;
	}
    }
    return false;
}

bool devicetree_device_t::store(reg_t addr, size_t len, const uint8_t* bytes)
{
    return true;
}

abstract_device_t *devicetree_device_t::make_device()
{
    std::cerr << "devicetree_device_t::make_device called" << std::endl;
    return new devicetree_device_t();
}

REGISTER_DEVICE(devicetree, 0x41000000, devicetree_device_t::make_device);
REGISTER_DEVICE(spikehw,    0x42000000, spikehw_device_t::make_device);
<|endoftext|>


<commit_before>#include <fstream>
#include <string>
#include <map>
#include <memory>
#include "core/message.h"
#include "edict_messages.h"
#include "lirch_plugin.h"

using namespace std;

void run(plugin_pipe pipe, std::string name)
{
	bool shutdown = false;
	pipe.write(registration_message::create(0, name, "display"));
	map<QString, unique_ptr<ofstream> > open_files;
	while(!shutdown)
	{
		message front = pipe.blocking_read();
		if(front.type == "shutdown")
		{
			shutdown = true;
		}
		else if(front.type == "registration_status")
		{
			registration_status * internals=dynamic_cast<registration_status *>(front.getdata());
			if (internals)
			{
				//This is a registration_status message, just like it said
				if (!internals->status)
					pipe.write(registration_message::create(internals->priority-1, name, internals->type));
			}
		}
		else if (front.type == "display")
		{
			display_message * internals = dynamic_cast<display_message *>(front.getdata());
			if(internals)
			{
				QString channelname = internals->channel;
				if(!open_files.count(channelname))
				{
					string filename(channelname.toUtf8().data());
					filename += ".txt";
					open_files[channelname] = unique_ptr<ofstream>(new ofstream());
					open_files[channelname]->open(filename.c_str(), fstream::app);
				}
				string output(internals->contents.toUtf8().data());
				open_files[channelname]->write(output.c_str(), sizeof output);
			}
		}
	}
	//done_message::create(name);
}
<commit_msg>Made logger bounce back messages<commit_after>#include <fstream>
#include <string>
#include <map>
#include <memory>
#include "core/message.h"
#include "edict_messages.h"
#include "lirch_plugin.h"

using namespace std;

void run(plugin_pipe pipe, std::string name)
{
	bool shutdown = false;
	pipe.write(registration_message::create(0, name, "display"));
	map<QString, unique_ptr<ofstream> > open_files;
	while(!shutdown)
	{
		message front = pipe.blocking_read();
		if(front.type == "shutdown")
		{
			shutdown = true;
		}
		else if(front.type == "registration_status")
		{
			registration_status * internals=dynamic_cast<registration_status *>(front.getdata());
			if (internals)
			{
				//This is a registration_status message, just like it said
				if (!internals->status)
					pipe.write(registration_message::create(internals->priority-1, name, internals->type));
			}
		}
		else if (front.type == "display")
		{
			display_message * internals = dynamic_cast<display_message *>(front.getdata());
			if(internals)
			{
				QString channelname = internals->channel;
				if(!open_files.count(channelname))
				{
					string filename(channelname.toUtf8().data());
					filename += ".txt";
					open_files[channelname] = unique_ptr<ofstream>(new ofstream());
					open_files[channelname]->open(filename.c_str(), fstream::app);
				}
				string output(internals->contents.toUtf8().data());
				open_files[channelname]->write(output.c_str(), sizeof output);
			}
			message bounceback;
			bounceback.type = "display";
			bounceback.data = internals->copy();
			pipe.write(bounceback);
		}
	}
	//done_message::create(name);
}
<|endoftext|>


<commit_before>/* mbed Microcontroller Library
 * Copyright (c) 2017 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "mbed_poll.h"
#include "FileHandle.h"
#if MBED_CONF_RTOS_PRESENT
#include "rtos/Kernel.h"
#include "rtos/Thread.h"
using namespace rtos;
#else
#include "Timer.h"
#include "LowPowerTimer.h"
#endif

namespace mbed {

// timeout -1 forever, or milliseconds
int poll(pollfh fhs[], unsigned nfhs, int timeout)
{
    /**
     * TODO Proper wake-up mechanism.
     * In order to correctly detect availability of read/write a FileHandle, we needed
     * a select or poll mechanisms. We opted for poll as POSIX defines in
     * http://pubs.opengroup.org/onlinepubs/009695399/functions/poll.html Currently,
     * mbed::poll() just spins and scans filehandles looking for any events we are
     * interested in. In future, his spinning behaviour will be replaced with
     * condition variables.
     */
#if MBED_CONF_RTOS_PRESENT
    uint64_t start_time = 0;
    if (timeout > 0) {
        start_time = Kernel::get_ms_count();
    }
#define TIME_ELAPSED() int64_t(Kernel::get_ms_count() - start_time)
#else
#if MBED_CONF_PLATFORM_POLL_USE_LOWPOWER_TIMER
    LowPowerTimer timer;
#else
    Timer timer;
#endif
    if (timeout > 0) {
        timer.start();
    }
#define TIME_ELAPSED() timer.read_ms()
#endif // MBED_CONF_RTOS_PRESENT

    int count = 0;
    for (;;) {
        /* Scan the file handles */
        for (unsigned n = 0; n < nfhs; n++) {
            FileHandle *fh = fhs[n].fh;
            short mask = fhs[n].events | POLLERR | POLLHUP | POLLNVAL;
            if (fh) {
                fhs[n].revents = fh->poll(mask) & mask;
            } else {
                fhs[n].revents = POLLNVAL;
            }
            if (fhs[n].revents) {
                count++;
            }
        }

        if (count) {
            break;
        }

        /* Nothing selected - this is where timeout handling would be needed */
        if (timeout == 0 || (timeout > 0 && TIME_ELAPSED() > timeout)) {
            break;
        }
#ifdef MBED_CONF_RTOS_PRESENT
        // TODO - proper blocking
        // wait for condition variable, wait queue whatever here
        rtos::Thread::wait(1);
#endif
    }
    return count;
}

} // namespace mbed
<commit_msg>poll: Un-doxygen internal comment<commit_after>/* mbed Microcontroller Library
 * Copyright (c) 2017 ARM Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "mbed_poll.h"
#include "FileHandle.h"
#if MBED_CONF_RTOS_PRESENT
#include "rtos/Kernel.h"
#include "rtos/Thread.h"
using namespace rtos;
#else
#include "Timer.h"
#include "LowPowerTimer.h"
#endif

namespace mbed {

// timeout -1 forever, or milliseconds
int poll(pollfh fhs[], unsigned nfhs, int timeout)
{
    /*
     * TODO Proper wake-up mechanism.
     * In order to correctly detect availability of read/write a FileHandle, we needed
     * a select or poll mechanisms. We opted for poll as POSIX defines in
     * http://pubs.opengroup.org/onlinepubs/009695399/functions/poll.html Currently,
     * mbed::poll() just spins and scans filehandles looking for any events we are
     * interested in. In future, his spinning behaviour will be replaced with
     * condition variables.
     */
#if MBED_CONF_RTOS_PRESENT
    uint64_t start_time = 0;
    if (timeout > 0) {
        start_time = Kernel::get_ms_count();
    }
#define TIME_ELAPSED() int64_t(Kernel::get_ms_count() - start_time)
#else
#if MBED_CONF_PLATFORM_POLL_USE_LOWPOWER_TIMER
    LowPowerTimer timer;
#else
    Timer timer;
#endif
    if (timeout > 0) {
        timer.start();
    }
#define TIME_ELAPSED() timer.read_ms()
#endif // MBED_CONF_RTOS_PRESENT

    int count = 0;
    for (;;) {
        /* Scan the file handles */
        for (unsigned n = 0; n < nfhs; n++) {
            FileHandle *fh = fhs[n].fh;
            short mask = fhs[n].events | POLLERR | POLLHUP | POLLNVAL;
            if (fh) {
                fhs[n].revents = fh->poll(mask) & mask;
            } else {
                fhs[n].revents = POLLNVAL;
            }
            if (fhs[n].revents) {
                count++;
            }
        }

        if (count) {
            break;
        }

        /* Nothing selected - this is where timeout handling would be needed */
        if (timeout == 0 || (timeout > 0 && TIME_ELAPSED() > timeout)) {
            break;
        }
#ifdef MBED_CONF_RTOS_PRESENT
        // TODO - proper blocking
        // wait for condition variable, wait queue whatever here
        rtos::Thread::wait(1);
#endif
    }
    return count;
}

} // namespace mbed
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "assert.hpp"
#include "Variable.hpp"
#include "Type.hpp"

#include "mtac/LiveVariableAnalysisProblem.hpp"
#include "mtac/Utils.hpp"

using namespace eddic;

typedef mtac::LiveVariableAnalysisProblem::ProblemDomain ProblemDomain;

void mtac::LiveVariableAnalysisProblem::Gather(std::shared_ptr<mtac::Function> function){
   for(auto& block : function->getBasicBlocks()){
        for(auto& statement : block->statements){
            //Passing a variable as param by address escape its liveness
            if(auto* ptr = boost::get<std::shared_ptr<mtac::Param>>(&statement)){
                auto& param = *ptr;

                if(param->address){
                    if(mtac::isVariable(param->arg)){
                        escaped_variables.insert(boost::get<std::shared_ptr<Variable>>(param->arg));
                    }
                }
            }
            //Taking the address of a variable escape its liveness
            else if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
                auto& quadruple = *ptr;

                auto type = quadruple->result->type();

                if(quadruple->op == mtac::Operator::ASSIGN && type->is_pointer()){
                    if(quadruple->arg1 && mtac::isVariable(*quadruple->arg1)){
                        escaped_variables.insert(boost::get<std::shared_ptr<Variable>>(*quadruple->arg1));
                    }
                } else if(quadruple->op == mtac::Operator::ARRAY_ASSIGN && type->is_array() && type->data_type()->is_pointer()){
                    if(quadruple->arg2 && mtac::isVariable(*quadruple->arg2)){
                        escaped_variables.insert(boost::get<std::shared_ptr<Variable>>(*quadruple->arg2));
                    }
                }
            }
        }
   }
}

ProblemDomain mtac::LiveVariableAnalysisProblem::Init(std::shared_ptr<mtac::Function> /*function*/){
    return default_element();
}

ProblemDomain mtac::LiveVariableAnalysisProblem::meet(ProblemDomain& out, ProblemDomain& in){
    if(out.top()){
        return in;
    } else if(in.top()){
        return out;
    }

    typename ProblemDomain::Values values;
    ProblemDomain result(values);

    for(auto& value : in.values()){
        result.values().insert(value);
    }

    for(auto& value : out.values()){
        result.values().insert(value);
    }

    return result;
}

template<typename Arg, typename Values>
void update(Arg& arg, Values& values){
    if(mtac::isVariable(arg)){
        auto var = boost::get<std::shared_ptr<Variable>>(arg);
        values.insert(var);
    }
}

template<typename Arg, typename Values>
void update_optional(Arg& arg, Values& values){
    if(arg){
        update(*arg, values);
    }
}

ProblemDomain mtac::LiveVariableAnalysisProblem::transfer(std::shared_ptr<mtac::BasicBlock>/* basic_block*/, mtac::Statement& statement, ProblemDomain& out){
    auto in = out;

    if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
        auto quadruple = *ptr;

        if(mtac::erase_result(quadruple->op)){
            in.values().erase(quadruple->result);
        }

        update_optional((*ptr)->arg1, in.values());
        update_optional((*ptr)->arg2, in.values());
    } else if(auto* ptr = boost::get<std::shared_ptr<mtac::Param>>(&statement)){
        update((*ptr)->arg, in.values());
    } else if(auto* ptr = boost::get<std::shared_ptr<mtac::IfFalse>>(&statement)){
        update((*ptr)->arg1, in.values());
        update_optional((*ptr)->arg2, in.values());
    } else if(auto* ptr = boost::get<std::shared_ptr<mtac::If>>(&statement)){
        update((*ptr)->arg1, in.values());
        update_optional((*ptr)->arg2, in.values());
    }

    for(auto& escaped_var : escaped_variables){
        in.values().insert(escaped_var);
    }

    return in;
}

bool mtac::LiveVariableAnalysisProblem::optimize(mtac::Statement& /*statement*/, std::shared_ptr<mtac::DataFlowResults<ProblemDomain>>& /*global_results*/){
    //This analysis is only made to gather information, not to optimize anything
    throw "Unimplemented";
}
<commit_msg>Cleanup<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2011.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "assert.hpp"
#include "Variable.hpp"
#include "Type.hpp"

#include "mtac/LiveVariableAnalysisProblem.hpp"
#include "mtac/Utils.hpp"

using namespace eddic;

typedef mtac::LiveVariableAnalysisProblem::ProblemDomain ProblemDomain;

void mtac::LiveVariableAnalysisProblem::Gather(std::shared_ptr<mtac::Function> function){
    for(auto& block : function->getBasicBlocks()){
        for(auto& statement : block->statements){
            //Passing a variable as param by address escape its liveness
            if(auto* ptr = boost::get<std::shared_ptr<mtac::Param>>(&statement)){
                auto& param = *ptr;

                if(param->address){
                    if(mtac::isVariable(param->arg)){
                        escaped_variables.insert(boost::get<std::shared_ptr<Variable>>(param->arg));
                    }
                }
            }
            //Taking the address of a variable escape its liveness
            else if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
                auto& quadruple = *ptr;

                auto type = quadruple->result->type();

                if(quadruple->op == mtac::Operator::ASSIGN && type->is_pointer()){
                    if(quadruple->arg1 && mtac::isVariable(*quadruple->arg1)){
                        escaped_variables.insert(boost::get<std::shared_ptr<Variable>>(*quadruple->arg1));
                    }
                } else if(quadruple->op == mtac::Operator::ARRAY_ASSIGN && type->is_array() && type->data_type()->is_pointer()){
                    if(quadruple->arg2 && mtac::isVariable(*quadruple->arg2)){
                        escaped_variables.insert(boost::get<std::shared_ptr<Variable>>(*quadruple->arg2));
                    }
                }
            }
        }
    }
}

ProblemDomain mtac::LiveVariableAnalysisProblem::Init(std::shared_ptr<mtac::Function> /*function*/){
    return default_element();
}

ProblemDomain mtac::LiveVariableAnalysisProblem::meet(ProblemDomain& out, ProblemDomain& in){
    if(out.top()){
        return in;
    } else if(in.top()){
        return out;
    }

    typename ProblemDomain::Values values;
    ProblemDomain result(values);

    for(auto& value : in.values()){
        result.values().insert(value);
    }

    for(auto& value : out.values()){
        result.values().insert(value);
    }

    return result;
}

template<typename Arg, typename Values>
void update(Arg& arg, Values& values){
    if(mtac::isVariable(arg)){
        auto var = boost::get<std::shared_ptr<Variable>>(arg);
        values.insert(var);
    }
}

template<typename Arg, typename Values>
void update_optional(Arg& arg, Values& values){
    if(arg){
        update(*arg, values);
    }
}

ProblemDomain mtac::LiveVariableAnalysisProblem::transfer(std::shared_ptr<mtac::BasicBlock>/* basic_block*/, mtac::Statement& statement, ProblemDomain& out){
    auto in = out;

    if(auto* ptr = boost::get<std::shared_ptr<mtac::Quadruple>>(&statement)){
        auto quadruple = *ptr;

        if(mtac::erase_result(quadruple->op)){
            in.values().erase(quadruple->result);
        }

        update_optional((*ptr)->arg1, in.values());
        update_optional((*ptr)->arg2, in.values());
    } else if(auto* ptr = boost::get<std::shared_ptr<mtac::Param>>(&statement)){
        update((*ptr)->arg, in.values());
    } else if(auto* ptr = boost::get<std::shared_ptr<mtac::IfFalse>>(&statement)){
        update((*ptr)->arg1, in.values());
        update_optional((*ptr)->arg2, in.values());
    } else if(auto* ptr = boost::get<std::shared_ptr<mtac::If>>(&statement)){
        update((*ptr)->arg1, in.values());
        update_optional((*ptr)->arg2, in.values());
    }

    for(auto& escaped_var : escaped_variables){
        in.values().insert(escaped_var);
    }

    return in;
}

bool mtac::LiveVariableAnalysisProblem::optimize(mtac::Statement& /*statement*/, std::shared_ptr<mtac::DataFlowResults<ProblemDomain>>& /*global_results*/){
    //This analysis is only made to gather information, not to optimize anything
    throw "Unimplemented";
}
<|endoftext|>