<commit_before>//
// Created by Benstone on 16/5/16.
//

#include <dlfcn.h>
#include <pthread.h>
#include <semaphore.h>

#include <cstring>
#include <map>

static bool is_mutex_inited = false;
static pthread_mutex_t sem_ptr_mutex;
static std::map<int, sem_t *> sem_ptrs;
static int sem_id = 0;
static const char *sem_prefix = "/AnonSem_";

int sem_init(sem_t *sem, int pshared, unsigned int value) {
	int id;
	char sem_name[strlen(sem_prefix) + 16];

	if (!is_mutex_inited) {
		pthread_mutex_init(&sem_ptr_mutex, NULL);
	}

	pthread_mutex_lock(&sem_ptr_mutex);
	id = sem_id++;
	pthread_mutex_unlock(&sem_ptr_mutex);

	sprintf(sem_name, "%s%d", sem_prefix, id);
	sem_unlink(sem_name);
	sem_t *sem_ptr = sem_open(sem_name, O_CREAT, pshared, value);
	if (sem_ptr == NULL) {
		return -1;
	}

	pthread_mutex_lock(&sem_ptr_mutex);
	sem_ptrs.insert(std::pair<int, sem_t *>(id, sem_ptr));
	pthread_mutex_unlock(&sem_ptr_mutex);

	*sem = id;
	return 0;
}

int sem_destroy(sem_t *sem) {
	char sem_name[strlen(sem_prefix) + 16];

	pthread_mutex_lock(&sem_ptr_mutex);
	int id = *sem;
	sem_t *sem_ptr = sem_ptrs[id];
	sem_ptrs.erase(id);
	pthread_mutex_unlock(&sem_ptr_mutex);

	sprintf(sem_name, "%s%d", sem_prefix, id);
	sem_close(sem_ptr);
	return sem_unlink(sem_name);
}

typedef int (*sem_func_ptr)(sem_t *);

int sem_post(sem_t *sem) {
	pthread_mutex_lock(&sem_ptr_mutex);
	sem_t *sem_ptr = sem_ptrs[*sem];
	pthread_mutex_unlock(&sem_ptr_mutex);
	sem_func_ptr post_ptr = (sem_func_ptr)dlsym(RTLD_NEXT, "sem_post");
	return (*post_ptr)(sem_ptr);
}

int sem_trywait(sem_t * sem) {
	pthread_mutex_lock(&sem_ptr_mutex);
	sem_t *sem_ptr = sem_ptrs[*sem];
	pthread_mutex_unlock(&sem_ptr_mutex);
	sem_func_ptr trywait_ptr = (sem_func_ptr)dlsym(RTLD_NEXT, "sem_trywait");
	return (*trywait_ptr)(sem_ptr);
}

int sem_wait(sem_t * sem) {
	pthread_mutex_lock(&sem_ptr_mutex);
	sem_t *sem_ptr = sem_ptrs[*sem];
	pthread_mutex_unlock(&sem_ptr_mutex);
	sem_func_ptr wait_ptr = (sem_func_ptr)dlsym(RTLD_NEXT, "sem_wait");
	return (*wait_ptr)(sem_ptr);
}

<commit_msg>derive the name of semaphore from pid<commit_after>//
// Created by Benstone on 16/5/16.
//

#ifndef HAVE_ANONYMOUS_SEMAPHORE

#include <sys/types.h>
#include <unistd.h>
#include <dlfcn.h>
#include <pthread.h>
#include <semaphore.h>

#include <cstring>
#include <map>

#ifndef OSX_ANON_SEM_NAME_PREFIX
#define OSX_ANON_SEM_NAME_PREFIX "/AnonSem"
#endif

#define OSX_POSIX_SEM_NAME_LEN 32

static bool is_mutex_inited = false;
static pthread_mutex_t sem_ptr_mutex;
static std::map<int, sem_t *> sem_ptrs;
static int sem_id = 0;
static const char *sem_prefix = OSX_ANON_SEM_NAME_PREFIX;

int sem_init(sem_t *sem, int pshared, unsigned int value) {
	pid_t pid;
	int id;
	char sem_name[OSX_POSIX_SEM_NAME_LEN];

	if (!is_mutex_inited) {
		pthread_mutex_init(&sem_ptr_mutex, NULL);
	}

	pthread_mutex_lock(&sem_ptr_mutex);
	id = sem_id++;
	pthread_mutex_unlock(&sem_ptr_mutex);

	pid = getpid();
	snprintf(sem_name, sizeof(sem_name), "%s/%d/%d", sem_prefix, pid, id);
	sem_unlink(sem_name);
	sem_t *sem_ptr = sem_open(sem_name, O_CREAT | O_EXCL, pshared, value);
	if (sem_ptr == NULL) {
		return -1;
	}

	pthread_mutex_lock(&sem_ptr_mutex);
	sem_ptrs.insert(std::pair<int, sem_t *>(id, sem_ptr));
	pthread_mutex_unlock(&sem_ptr_mutex);

	*sem = id;
	return 0;
}

int sem_destroy(sem_t *sem) {
	pid_t pid;
	char sem_name[OSX_POSIX_SEM_NAME_LEN];

	pthread_mutex_lock(&sem_ptr_mutex);
	int id = *sem;
	sem_t *sem_ptr = sem_ptrs[id];
	sem_ptrs.erase(id);
	pthread_mutex_unlock(&sem_ptr_mutex);

	pid = getpid();
	snprintf(sem_name, sizeof(sem_name), "%s/%d/%d", sem_prefix, pid, id);
	sem_close(sem_ptr);
	return sem_unlink(sem_name);
}

typedef int (*sem_func_ptr)(sem_t *);

int sem_post(sem_t *sem) {
	pthread_mutex_lock(&sem_ptr_mutex);
	sem_t *sem_ptr = sem_ptrs[*sem];
	pthread_mutex_unlock(&sem_ptr_mutex);
	sem_func_ptr post_ptr = (sem_func_ptr)dlsym(RTLD_NEXT, "sem_post");
	return (*post_ptr)(sem_ptr);
}

int sem_trywait(sem_t * sem) {
	pthread_mutex_lock(&sem_ptr_mutex);
	sem_t *sem_ptr = sem_ptrs[*sem];
	pthread_mutex_unlock(&sem_ptr_mutex);
	sem_func_ptr trywait_ptr = (sem_func_ptr)dlsym(RTLD_NEXT, "sem_trywait");
	return (*trywait_ptr)(sem_ptr);
}

int sem_wait(sem_t * sem) {
	pthread_mutex_lock(&sem_ptr_mutex);
	sem_t *sem_ptr = sem_ptrs[*sem];
	pthread_mutex_unlock(&sem_ptr_mutex);
	sem_func_ptr wait_ptr = (sem_func_ptr)dlsym(RTLD_NEXT, "sem_wait");
	return (*wait_ptr)(sem_ptr);
}

#endif

<|endoftext|>


<commit_before>#ifndef __OPENTREP_BAS_FLOAT_UTILS_GOOGLE_HPP
#define __OPENTREP_BAS_FLOAT_UTILS_GOOGLE_HPP

// 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.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// 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 COPYRIGHT
// OWNER 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.
//
// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
//
// The Google C++ Testing Framework (Google Test)

// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <limits>

// This template class serves as a compile-time function from size to
// type.  It maps a size in bytes to a primitive type with that
// size. e.g.
//
//   TypeWithSize<4>::UInt
//
// is typedef-ed to be unsigned int (unsigned integer made up of 4
// bytes).
//
// Such functionality should belong to STL, but I cannot find it
// there.
//
// Google Test uses this class in the implementation of floating-point
// comparison.
//
// For now it only handles UInt (unsigned int) as that's all Google Test
// needs.  Other types can be easily added in the future if need
// arises.
template <size_t size>
class TypeWithSize {
 public:
  // This prevents the user from using TypeWithSize<N> with incorrect
  // values of N.
  typedef void UInt;
};

// The specialization for size 4.
template <>
class TypeWithSize<4> {
 public:
  // unsigned int has size 4 in both gcc and MSVC.
  //
  // As base/basictypes.h doesn't compile on Windows, we cannot use
  // uint32, uint64, and etc here.
  typedef int Int;
  typedef unsigned int UInt;
};

// The specialization for size 8.
template <>
class TypeWithSize<8> {
 public:
#if GTEST_OS_WINDOWS
  typedef __int64 Int;
  typedef unsigned __int64 UInt;
#else
  typedef long long Int;  // NOLINT
  typedef unsigned long long UInt;  // NOLINT
#endif  // GTEST_OS_WINDOWS
};

// This template class represents an IEEE floating-point number
// (either single-precision or double-precision, depending on the
// template parameters).
//
// The purpose of this class is to do more sophisticated number
// comparison.  (Due to round-off error, etc, it's very unlikely that
// two floating-points will be equal exactly.  Hence a naive
// comparison by the == operation often doesn't work.)
//
// Format of IEEE floating-point:
//
//   The most-significant bit being the leftmost, an IEEE
//   floating-point looks like
//
//     sign_bit exponent_bits fraction_bits
//
//   Here, sign_bit is a single bit that designates the sign of the
//   number.
//
//   For float, there are 8 exponent bits and 23 fraction bits.
//
//   For double, there are 11 exponent bits and 52 fraction bits.
//
//   More details can be found at
//   http://en.wikipedia.org/wiki/IEEE_floating-point_standard.
//
// Template parameter:
//
//   RawType: the raw floating-point type (either float or double)
template <typename RawType>
class FloatingPoint {
 public:
  // Defines the unsigned integer type that has the same size as the
  // floating point number.
  typedef typename TypeWithSize<sizeof(RawType)>::UInt Bits;

  // Constants.

  // # of bits in a number.
  static const size_t kBitCount = 8*sizeof(RawType);

  // # of fraction bits in a number.
  static const size_t kFractionBitCount =
    std::numeric_limits<RawType>::digits - 1;

  // # of exponent bits in a number.
  static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;

  // The mask for the sign bit.
  static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);

  // The mask for the fraction bits.
  static const Bits kFractionBitMask =
    ~static_cast<Bits>(0) >> (kExponentBitCount + 1);

  // The mask for the exponent bits.
  static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);

  // How many ULP's (Units in the Last Place) we want to tolerate when
  // comparing two numbers.  The larger the value, the more error we
  // allow.  A 0 value means that two numbers must be exactly the same
  // to be considered equal.
  //
  // The maximum error of a single floating-point operation is 0.5
  // units in the last place.  On Intel CPU's, all floating-point
  // calculations are done with 80-bit precision, while double has 64
  // bits.  Therefore, 4 should be enough for ordinary use.
  //
  // See the following article for more details on ULP:
  // http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm.
  static const size_t kMaxUlps = 4;

  // Constructs a FloatingPoint from a raw floating-point number.
  //
  // On an Intel CPU, passing a non-normalized NAN (Not a Number)
  // around may change its bits, although the new value is guaranteed
  // to be also a NAN.  Therefore, don't expect this constructor to
  // preserve the bits in x when x is a NAN.
  explicit FloatingPoint (const RawType& x) { u_.value_ = x; }

  // Static methods

  // Reinterprets a bit pattern as a floating-point number.
  //
  // This function is needed to test the AlmostEquals() method.
  static RawType ReinterpretBits(const Bits bits) {
    FloatingPoint fp(0);
    fp.u_.bits_ = bits;
    return fp.u_.value_;
  }

  // Returns the floating-point number that represent positive infinity.
  static RawType Infinity() {
    return ReinterpretBits(kExponentBitMask);
  }

  // Non-static methods

  // Returns the bits that represents this number.
  const Bits &bits() const { return u_.bits_; }

  // Returns the exponent bits of this number.
  Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }

  // Returns the fraction bits of this number.
  Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }

  // Returns the sign bit of this number.
  Bits sign_bit() const { return kSignBitMask & u_.bits_; }

  // Returns true iff this is NAN (not a number).
  bool is_nan() const {
    // It's a NAN if the exponent bits are all ones and the fraction
    // bits are not entirely zeros.
    return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
  }

  // Returns true iff this number is at most kMaxUlps ULP's away from
  // rhs.  In particular, this function:
  //
  //   - returns false if either number is (or both are) NAN.
  //   - treats really large numbers as almost equal to infinity.
  //   - thinks +0.0 and -0.0 are 0 DLP's apart.
  bool AlmostEquals(const FloatingPoint& rhs) const {
    // The IEEE standard says that any comparison operation involving
    // a NAN must return false.
    if (is_nan() || rhs.is_nan()) return false;

    return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_)
        <= kMaxUlps;
  }

 private:
  // The data type used to store the actual floating-point number.
  union FloatingPointUnion {
    RawType value_;  // The raw floating-point number.
    Bits bits_;      // The bits that represent the number.
  };

  // Converts an integer from the sign-and-magnitude representation to
  // the biased representation.  More precisely, let N be 2 to the
  // power of (kBitCount - 1), an integer x is represented by the
  // unsigned number x + N.
  //
  // For instance,
  //
  //   -N + 1 (the most negative number representable using
  //          sign-and-magnitude) is represented by 1;
  //   0      is represented by N; and
  //   N - 1  (the biggest number representable using
  //          sign-and-magnitude) is represented by 2N - 1.
  //
  // Read http://en.wikipedia.org/wiki/Signed_number_representations
  // for more details on signed number representations.
  static Bits SignAndMagnitudeToBiased(const Bits &sam) {
    if (kSignBitMask & sam) {
      // sam represents a negative number.
      return ~sam + 1;
    } else {
      // sam represents a positive number.
      return kSignBitMask | sam;
    }
  }

  // Given two numbers in the sign-and-magnitude representation,
  // returns the distance between them as an unsigned number.
  static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
                                                     const Bits &sam2) {
    const Bits biased1 = SignAndMagnitudeToBiased(sam1);
    const Bits biased2 = SignAndMagnitudeToBiased(sam2);
    return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
  }

  FloatingPointUnion u_;
};

#endif // __OPENTREP_BAS_FLOAT_UTILS_GOOGLE_HPP
<commit_msg>[Doc] Specified the license for the floating point utility<commit_after>#ifndef __OPENTREP_BAS_FLOAT_UTILS_GOOGLE_HPP
#define __OPENTREP_BAS_FLOAT_UTILS_GOOGLE_HPP

// 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.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// 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 COPYRIGHT
// OWNER 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.
//
// Authors: wan@google.com (Zhanyong Wan), eefacm@gmail.com (Sean Mcafee)
// License: MIT
//
// The Google C++ Testing Framework (Google Test)

// //////////////////////////////////////////////////////////////////////
// Import section
// //////////////////////////////////////////////////////////////////////
// STL
#include <limits>

// This template class serves as a compile-time function from size to
// type.  It maps a size in bytes to a primitive type with that
// size. e.g.
//
//   TypeWithSize<4>::UInt
//
// is typedef-ed to be unsigned int (unsigned integer made up of 4
// bytes).
//
// Such functionality should belong to STL, but I cannot find it
// there.
//
// Google Test uses this class in the implementation of floating-point
// comparison.
//
// For now it only handles UInt (unsigned int) as that's all Google Test
// needs.  Other types can be easily added in the future if need
// arises.
template <size_t size>
class TypeWithSize {
 public:
  // This prevents the user from using TypeWithSize<N> with incorrect
  // values of N.
  typedef void UInt;
};

// The specialization for size 4.
template <>
class TypeWithSize<4> {
 public:
  // unsigned int has size 4 in both gcc and MSVC.
  //
  // As base/basictypes.h doesn't compile on Windows, we cannot use
  // uint32, uint64, and etc here.
  typedef int Int;
  typedef unsigned int UInt;
};

// The specialization for size 8.
template <>
class TypeWithSize<8> {
 public:
#if GTEST_OS_WINDOWS
  typedef __int64 Int;
  typedef unsigned __int64 UInt;
#else
  typedef long long Int;  // NOLINT
  typedef unsigned long long UInt;  // NOLINT
#endif  // GTEST_OS_WINDOWS
};

// This template class represents an IEEE floating-point number
// (either single-precision or double-precision, depending on the
// template parameters).
//
// The purpose of this class is to do more sophisticated number
// comparison.  (Due to round-off error, etc, it's very unlikely that
// two floating-points will be equal exactly.  Hence a naive
// comparison by the == operation often doesn't work.)
//
// Format of IEEE floating-point:
//
//   The most-significant bit being the leftmost, an IEEE
//   floating-point looks like
//
//     sign_bit exponent_bits fraction_bits
//
//   Here, sign_bit is a single bit that designates the sign of the
//   number.
//
//   For float, there are 8 exponent bits and 23 fraction bits.
//
//   For double, there are 11 exponent bits and 52 fraction bits.
//
//   More details can be found at
//   http://en.wikipedia.org/wiki/IEEE_floating-point_standard.
//
// Template parameter:
//
//   RawType: the raw floating-point type (either float or double)
template <typename RawType>
class FloatingPoint {
 public:
  // Defines the unsigned integer type that has the same size as the
  // floating point number.
  typedef typename TypeWithSize<sizeof(RawType)>::UInt Bits;

  // Constants.

  // # of bits in a number.
  static const size_t kBitCount = 8*sizeof(RawType);

  // # of fraction bits in a number.
  static const size_t kFractionBitCount =
    std::numeric_limits<RawType>::digits - 1;

  // # of exponent bits in a number.
  static const size_t kExponentBitCount = kBitCount - 1 - kFractionBitCount;

  // The mask for the sign bit.
  static const Bits kSignBitMask = static_cast<Bits>(1) << (kBitCount - 1);

  // The mask for the fraction bits.
  static const Bits kFractionBitMask =
    ~static_cast<Bits>(0) >> (kExponentBitCount + 1);

  // The mask for the exponent bits.
  static const Bits kExponentBitMask = ~(kSignBitMask | kFractionBitMask);

  // How many ULP's (Units in the Last Place) we want to tolerate when
  // comparing two numbers.  The larger the value, the more error we
  // allow.  A 0 value means that two numbers must be exactly the same
  // to be considered equal.
  //
  // The maximum error of a single floating-point operation is 0.5
  // units in the last place.  On Intel CPU's, all floating-point
  // calculations are done with 80-bit precision, while double has 64
  // bits.  Therefore, 4 should be enough for ordinary use.
  //
  // See the following article for more details on ULP:
  // http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm.
  static const size_t kMaxUlps = 4;

  // Constructs a FloatingPoint from a raw floating-point number.
  //
  // On an Intel CPU, passing a non-normalized NAN (Not a Number)
  // around may change its bits, although the new value is guaranteed
  // to be also a NAN.  Therefore, don't expect this constructor to
  // preserve the bits in x when x is a NAN.
  explicit FloatingPoint (const RawType& x) { u_.value_ = x; }

  // Static methods

  // Reinterprets a bit pattern as a floating-point number.
  //
  // This function is needed to test the AlmostEquals() method.
  static RawType ReinterpretBits(const Bits bits) {
    FloatingPoint fp(0);
    fp.u_.bits_ = bits;
    return fp.u_.value_;
  }

  // Returns the floating-point number that represent positive infinity.
  static RawType Infinity() {
    return ReinterpretBits(kExponentBitMask);
  }

  // Non-static methods

  // Returns the bits that represents this number.
  const Bits &bits() const { return u_.bits_; }

  // Returns the exponent bits of this number.
  Bits exponent_bits() const { return kExponentBitMask & u_.bits_; }

  // Returns the fraction bits of this number.
  Bits fraction_bits() const { return kFractionBitMask & u_.bits_; }

  // Returns the sign bit of this number.
  Bits sign_bit() const { return kSignBitMask & u_.bits_; }

  // Returns true iff this is NAN (not a number).
  bool is_nan() const {
    // It's a NAN if the exponent bits are all ones and the fraction
    // bits are not entirely zeros.
    return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
  }

  // Returns true iff this number is at most kMaxUlps ULP's away from
  // rhs.  In particular, this function:
  //
  //   - returns false if either number is (or both are) NAN.
  //   - treats really large numbers as almost equal to infinity.
  //   - thinks +0.0 and -0.0 are 0 DLP's apart.
  bool AlmostEquals(const FloatingPoint& rhs) const {
    // The IEEE standard says that any comparison operation involving
    // a NAN must return false.
    if (is_nan() || rhs.is_nan()) return false;

    return DistanceBetweenSignAndMagnitudeNumbers(u_.bits_, rhs.u_.bits_)
        <= kMaxUlps;
  }

 private:
  // The data type used to store the actual floating-point number.
  union FloatingPointUnion {
    RawType value_;  // The raw floating-point number.
    Bits bits_;      // The bits that represent the number.
  };

  // Converts an integer from the sign-and-magnitude representation to
  // the biased representation.  More precisely, let N be 2 to the
  // power of (kBitCount - 1), an integer x is represented by the
  // unsigned number x + N.
  //
  // For instance,
  //
  //   -N + 1 (the most negative number representable using
  //          sign-and-magnitude) is represented by 1;
  //   0      is represented by N; and
  //   N - 1  (the biggest number representable using
  //          sign-and-magnitude) is represented by 2N - 1.
  //
  // Read http://en.wikipedia.org/wiki/Signed_number_representations
  // for more details on signed number representations.
  static Bits SignAndMagnitudeToBiased(const Bits &sam) {
    if (kSignBitMask & sam) {
      // sam represents a negative number.
      return ~sam + 1;
    } else {
      // sam represents a positive number.
      return kSignBitMask | sam;
    }
  }

  // Given two numbers in the sign-and-magnitude representation,
  // returns the distance between them as an unsigned number.
  static Bits DistanceBetweenSignAndMagnitudeNumbers(const Bits &sam1,
                                                     const Bits &sam2) {
    const Bits biased1 = SignAndMagnitudeToBiased(sam1);
    const Bits biased2 = SignAndMagnitudeToBiased(sam2);
    return (biased1 >= biased2) ? (biased1 - biased2) : (biased2 - biased1);
  }

  FloatingPointUnion u_;
};

#endif // __OPENTREP_BAS_FLOAT_UTILS_GOOGLE_HPP
<|endoftext|>


<commit_before>#include <ctime>
#include <deque>
#include <GL/glut.h>
#include <unistd.h>
#include <iostream>
#include <algorithm>
#include "pipe.h"
using namespace std;

int main(int argc, char** argv){

    //Initializing variables
    title = "OpenGL Pipe";
    map_half_length = 14.0f;
    direction = 2;
    move_speed = 25;
    last_direction = 2;
    screenW = 1920;
    screenH = 1080;

    //Init glut
    glutInit(&argc, argv);
    glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH);

    glutInitWindowSize(screenW, screenH);
    glutCreateWindow(title);
    glutFullScreen();

    //Set the glut functions
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(processKeys);
    glutSpecialFunc(processSpecial);

    red = rand()%255;
    green =rand()%255;
    blue =rand()%255;

    vector<float> point;
    int x = rand()%(int)(map_half_length*2);
    point.push_back((float)x);
    int y = rand()%(int)(map_half_length*2);
    point.push_back((float)y);
    int z = rand()%(int)(map_half_length*2);
    point.push_back((float)z);
    part_coords.push_back(point);
    map[x+1][y+1][z+1]=1;

    srand(time(NULL));
    constructMap();

    initGL();
    glutTimerFunc(move_speed, grow, 0);
    glutMainLoop();

    delete title;
    return 0;
}

void grow(int value){
    /*
        Directions:
        0 - up
        1 - down
        2 - right
        3 - left
        4 - out
        5 - in
    */
    UNUSED(value);

    if(part_coords.size() > 200){
        reset();
    }

    if(part_coords2.size() > 2000) {
      part_coords2.clear();
    }

    //Get the last coordinates
    int last_part = part_coords.size() - 1;
    vector<float> new_head = part_coords[last_part];

    if(map[(int)new_head[0]+1][(int)new_head[1]+2][(int)new_head[2]+1]==0){
        directions.push_back(0);
    }
    if(map[(int)new_head[0]+1][(int)new_head[1]][(int)new_head[2]+1]==0){
        directions.push_back(1);
    }
    if(map[(int)new_head[0]+2][(int)new_head[1]+1][(int)new_head[2]+1]==0){
        directions.push_back(2);
    }
    if(map[(int)new_head[0]][(int)new_head[1]+1][(int)new_head[2]+1]==0){
        directions.push_back(3);
    }
    if(map[(int)new_head[0]+1][(int)new_head[1]+1][(int)new_head[2]+2]==0){
        directions.push_back(4);
    }
    if(map[(int)new_head[0]+1][(int)new_head[1]+1][(int)new_head[2]]==0){
        directions.push_back(5);
    }

    //Reset if no valid directions
    if(directions.empty()){
        reset();
        grow(1);
        return;
    }

    // Add extra directions for the current direction to encourage moving forward
    for(int n:directions){
        if(n == last_direction){
            for(int i=0; i<10; i++){
                directions.push_back(last_direction);
            }
        }
    }

    //Choose direction to move out of valid directions
    int direction = directions.at(rand()%directions.size());

    //create a new point depending on that direction
    switch(direction){
        case 0:
            last_direction = 0;
            new_head[0] = new_head[0];
            new_head[1] = new_head[1]+1;
            new_head[2] = new_head[2];
            break;
        case 1:
            last_direction = 1;
            new_head[0] = new_head[0];
            new_head[1] = new_head[1]-1;
            new_head[2] = new_head[2];
            break;
        case 2:
            last_direction = 2;
            new_head[0] = new_head[0]+1;
            new_head[1] = new_head[1];
            new_head[2] = new_head[2];
            break;
         case 3:
            last_direction = 3;
            new_head[0] = new_head[0]-1;
            new_head[1] = new_head[1];
            new_head[2] = new_head[2];
            break;
        case 4:
            last_direction = 4;
            new_head[0] = new_head[0];
            new_head[1] = new_head[1];
            new_head[2] = new_head[2]+1;
            break;
        case 5:
            last_direction = 5;
            new_head[0] = new_head[0];
            new_head[1] = new_head[1];
            new_head[2] = new_head[2]-1;
            break;
    }

    //add a value to the map where there is a pipe representing the direction
    // that the pipe is moving
    map[(int)new_head[0]+1][(int)new_head[1]+1][(int)new_head[2]+1] = direction/2 + 1;

    std::vector<GLubyte> current_color;

    current_color.push_back(red);
    current_color.push_back(green);
    current_color.push_back(blue);
    color.push_back(current_color);

    //Push the new head onto the coords
    part_coords.push_back(new_head);

    directions.clear();
    glutTimerFunc(move_speed, grow, 0);
}

void reset(){
    cout << "RESETING "<< reset_val << endl;
    reset_val += 1;

    // adds the current pipe to the queue of all created pipes on the screen
    part_coords2.insert( part_coords2.end(), part_coords.begin(), part_coords.end() );
    for (int i=0; i<WIDTH+2; i++) {
      for (int j=0; j<HEIGHT+2; j++) {
        for (int k=0; k<DEPTH+2; k++) {
          map2[i][j][k] += map[i][j][k];
        }
      }
    }

    part_coords.clear();
    constructMap();

    std::vector<float> point;
    int x = rand()%(int)(map_half_length*2);
    point.push_back((float)x);
    int y = rand()%(int)(map_half_length*2);
    point.push_back((float)y);
    int z = rand()%(int)(map_half_length*2);
    point.push_back((float)z);
    map[x+1][y+1][z+1]=1;

    part_coords.push_back(point);

    red = rand()%255;
    green =rand()%255;
    blue =rand()%255;

    std::vector<GLubyte> current_color;
    current_color.push_back(red);
    current_color.push_back(green);
    current_color.push_back(blue);
    color.push_back(current_color);
}

void constructMap(){
    /*
        Constructs the map with walls being 1 and all other space 0
    */
    for(int row=0; row<WIDTH+2; row++){
        for(int col=0; col<HEIGHT+2; col++){
            for(int z=0; z<DEPTH+2; z++){
                if(row==0 || col==0 || z==0){
                    map[row][col][z] = 1;
                }
                else if(row==HEIGHT+1 || col==WIDTH+1 || z==DEPTH+1){
                    map[row][col][z] = 1;
                }
                else{
                    map[row][col][z] = 0;
                }
            }
        }
    }
}

void processKeys(unsigned char key, int x, int y){
    switch(key){
        case 27:
            exit(0);
            break;
        default:
            return;
    }
}
void processSpecial(int key, int x, int y){
    cout<<key<<endl;
}

void initGL(){
    glEnable(GL_DEPTH_TEST);
    glMatrixMode(GL_PROJECTION);
    glDepthFunc(GL_LEQUAL);
    glShadeModel(GL_SMOOTH);
    gluPerspective(75.0f, (float)screenW/screenH, 0.0f, 35.0f);

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

void reshape(GLsizei width, GLsizei height){
    screenW = width;
    screenH = height;
    glutReshapeWindow(width, height);
}

void display(){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);

    /*UNCOMMENT NEXT THREE LINE FOR MELLOW PARTY MODE*/
    // red = rand()%255;
    // green =rand()%255;
    // blue =rand()%255;

    for(unsigned int a = 0; a < part_coords.size(); a++){
        glLoadIdentity();

        /*UNCOMMENT NEXT THREE LINE FOR FULL PARTY MODE*/
        // red = rand()%255;
        // green =rand()%255;
        // blue =rand()%255;

        x = part_coords[a][0];
        y = part_coords[a][1];
        z = part_coords[a][2];

        glTranslatef(x-(WIDTH+1)/2, -y+(HEIGHT+1)/2, z-2*DEPTH);

        //glutSolidSphere(12.0, 50, 50);
        if(map[x+1][y+1][z+1] == 2){
            glRotatef(90, 0.0f, 1.0f, 0.0f);
        }
        if(map[x+1][y+1][z+1] == 1){
            glRotatef(90, 1.0f, 0.0f, 0.0f);
        }

        glBegin(GL_QUAD_STRIP);
            glColor3ub(red, green, blue);
            GLfloat COSan_3 = 0.0;
            GLfloat SINan_3 = 0.0;
            for(GLfloat an = 0.0; an <= 2.0 * M_PI; an += M_PI / 12.0) {
                        glNormal3f((COSan_3 = cos(an)/3.0), (SINan_3 = sin(an)/3.0), 2.0);
                        glVertex3f(COSan_3, SINan_3, 0.5f);
                        glVertex3f(COSan_3, SINan_3, -0.5f);
        }
        glEnd();
    }
    for(unsigned int b = 0; b < part_coords2.size(); b++){
        glLoadIdentity();

        x = part_coords2[b][0];
        y = part_coords2[b][1];
        z = part_coords2[b][2];

        glTranslatef(x-(WIDTH+1)/2, -y+(HEIGHT+1)/2, z-2*DEPTH);

        if(map2[x+1][y+1][z+1] == 2){
            glRotatef(90, 0.0f, 1.0f, 0.0f);
        }
        if(map2[x+1][y+1][z+1] == 1){
            glRotatef(90, 1.0f, 0.0f, 0.0f);
        }

        glBegin(GL_QUAD_STRIP);
            glColor3ub(color.at(b)[0], color.at(b)[1], color.at(b)[2]);
            GLfloat COSan_3 = 0.0;
            GLfloat SINan_3 = 0.0;
            for(GLfloat an = 0.0; an <= 2.0 * M_PI; an += M_PI / 12.0) {
                        glNormal3f((COSan_3 = cos(an)/3.0), (SINan_3 = sin(an)/3.0), 2.0);
                        glVertex3f(COSan_3, SINan_3, 0.5f);
                        glVertex3f(COSan_3, SINan_3, -0.5f);
        }
        glEnd();
    }
    glutSwapBuffers();
}
<commit_msg>fix: color problem<commit_after>#include <ctime>
#include <deque>
#include <GL/glut.h>
#include <unistd.h>
#include <iostream>
#include <algorithm>
#include "pipe.h"
using namespace std;

int main(int argc, char** argv){

    //Initializing variables
    title = "OpenGL Pipe";
    map_half_length = 14.0f;
    direction = 2;
    move_speed = 25;
    last_direction = 2;
    screenW = 1920;
    screenH = 1080;

    //Init glut
    glutInit(&argc, argv);
    glutInitDisplayMode (GLUT_DOUBLE | GLUT_DEPTH);

    glutInitWindowSize(screenW, screenH);
    glutCreateWindow(title);
    glutFullScreen();

    //Set the glut functions
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(processKeys);
    glutSpecialFunc(processSpecial);

    rand();
    red = rand()%255;
    green =rand()%255;
    blue =rand()%255;

    std::vector<GLubyte> current_color;
    current_color.push_back(red);
    current_color.push_back(green);
    current_color.push_back(blue);
    color.push_back(current_color);

    vector<float> point;
    int x = rand()%(int)(map_half_length*2);
    point.push_back((float)x);
    int y = rand()%(int)(map_half_length*2);
    point.push_back((float)y);
    int z = rand()%(int)(map_half_length*2);
    point.push_back((float)z);
    part_coords.push_back(point);
    map[x+1][y+1][z+1]=1;

    srand(time(NULL));
    constructMap();

    initGL();
    glutTimerFunc(move_speed, grow, 0);
    glutMainLoop();

    delete title;
    return 0;
}

void grow(int value){
    /*
        Directions:
        0 - up
        1 - down
        2 - right
        3 - left
        4 - out
        5 - in
    */
    UNUSED(value);

    if(part_coords.size() > 200){
        reset();
    }

    if(part_coords2.size() > 2000) {
      part_coords2.clear();
    }

    //Get the last coordinates
    int last_part = part_coords.size() - 1;
    vector<float> new_head = part_coords[last_part];

    if(map[(int)new_head[0]+1][(int)new_head[1]+2][(int)new_head[2]+1]==0){
        directions.push_back(0);
    }
    if(map[(int)new_head[0]+1][(int)new_head[1]][(int)new_head[2]+1]==0){
        directions.push_back(1);
    }
    if(map[(int)new_head[0]+2][(int)new_head[1]+1][(int)new_head[2]+1]==0){
        directions.push_back(2);
    }
    if(map[(int)new_head[0]][(int)new_head[1]+1][(int)new_head[2]+1]==0){
        directions.push_back(3);
    }
    if(map[(int)new_head[0]+1][(int)new_head[1]+1][(int)new_head[2]+2]==0){
        directions.push_back(4);
    }
    if(map[(int)new_head[0]+1][(int)new_head[1]+1][(int)new_head[2]]==0){
        directions.push_back(5);
    }

    //Reset if no valid directions
    if(directions.empty()){
        reset();
        grow(1);
        return;
    }

    // Add extra directions for the current direction to encourage moving forward
    for(int n:directions){
        if(n == last_direction){
            for(int i=0; i<10; i++){
                directions.push_back(last_direction);
            }
        }
    }

    //Choose direction to move out of valid directions
    int direction = directions.at(rand()%directions.size());

    //create a new point depending on that direction
    switch(direction){
        case 0:
            last_direction = 0;
            new_head[0] = new_head[0];
            new_head[1] = new_head[1]+1;
            new_head[2] = new_head[2];
            break;
        case 1:
            last_direction = 1;
            new_head[0] = new_head[0];
            new_head[1] = new_head[1]-1;
            new_head[2] = new_head[2];
            break;
        case 2:
            last_direction = 2;
            new_head[0] = new_head[0]+1;
            new_head[1] = new_head[1];
            new_head[2] = new_head[2];
            break;
         case 3:
            last_direction = 3;
            new_head[0] = new_head[0]-1;
            new_head[1] = new_head[1];
            new_head[2] = new_head[2];
            break;
        case 4:
            last_direction = 4;
            new_head[0] = new_head[0];
            new_head[1] = new_head[1];
            new_head[2] = new_head[2]+1;
            break;
        case 5:
            last_direction = 5;
            new_head[0] = new_head[0];
            new_head[1] = new_head[1];
            new_head[2] = new_head[2]-1;
            break;
    }

    //add a value to the map where there is a pipe representing the direction
    // that the pipe is moving
    map[(int)new_head[0]+1][(int)new_head[1]+1][(int)new_head[2]+1] = direction/2 + 1;

    std::vector<GLubyte> current_color;

    current_color.push_back(red);
    current_color.push_back(green);
    current_color.push_back(blue);
    color.push_back(current_color);

    //Push the new head onto the coords
    part_coords.push_back(new_head);

    directions.clear();
    glutTimerFunc(move_speed, grow, 0);
}

void reset(){
    cout << "RESETING "<< reset_val << endl;
    reset_val += 1;

    // adds the current pipe to the queue of all created pipes on the screen
    part_coords2.insert( part_coords2.end(), part_coords.begin(), part_coords.end() );
    for (int i=0; i<WIDTH+2; i++) {
      for (int j=0; j<HEIGHT+2; j++) {
        for (int k=0; k<DEPTH+2; k++) {
          map2[i][j][k] += map[i][j][k];
        }
      }
    }

    part_coords.clear();
    constructMap();

    red = rand()%255;
    green =rand()%255;
    blue =rand()%255;

    std::vector<GLubyte> current_color;
    current_color.push_back(red);
    current_color.push_back(green);
    current_color.push_back(blue);
    color.push_back(current_color);

    std::vector<float> point;
    int x = rand()%(int)(map_half_length*2);
    point.push_back((float)x);
    int y = rand()%(int)(map_half_length*2);
    point.push_back((float)y);
    int z = rand()%(int)(map_half_length*2);
    point.push_back((float)z);
    map[x+1][y+1][z+1]=1;

    part_coords.push_back(point);
}

void constructMap(){
    /*
        Constructs the map with walls being 1 and all other space 0
    */
    for(int row=0; row<WIDTH+2; row++){
        for(int col=0; col<HEIGHT+2; col++){
            for(int z=0; z<DEPTH+2; z++){
                if(row==0 || col==0 || z==0){
                    map[row][col][z] = 1;
                }
                else if(row==HEIGHT+1 || col==WIDTH+1 || z==DEPTH+1){
                    map[row][col][z] = 1;
                }
                else{
                    map[row][col][z] = 0;
                }
            }
        }
    }
}

void processKeys(unsigned char key, int x, int y){
    switch(key){
        case 27:
            exit(0);
            break;
        default:
            return;
    }
}
void processSpecial(int key, int x, int y){
    cout<<key<<endl;
}

void initGL(){
    glEnable(GL_DEPTH_TEST);
    glMatrixMode(GL_PROJECTION);
    glDepthFunc(GL_LEQUAL);
    glShadeModel(GL_SMOOTH);
    gluPerspective(75.0f, (float)screenW/screenH, 0.0f, 35.0f);

    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

void reshape(GLsizei width, GLsizei height){
    screenW = width;
    screenH = height;
    glutReshapeWindow(width, height);
}

void display(){
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glMatrixMode(GL_MODELVIEW);

    /*UNCOMMENT NEXT THREE LINE FOR MELLOW PARTY MODE*/
    // red = rand()%255;
    // green =rand()%255;
    // blue =rand()%255;

    for(unsigned int a = 0; a < part_coords.size(); a++){
        glLoadIdentity();

        /*UNCOMMENT NEXT THREE LINE FOR FULL PARTY MODE*/
        // red = rand()%255;
        // green =rand()%255;
        // blue =rand()%255;

        x = part_coords[a][0];
        y = part_coords[a][1];
        z = part_coords[a][2];

        glTranslatef(x-(WIDTH+1)/2, -y+(HEIGHT+1)/2, z-2*DEPTH);

        //glutSolidSphere(12.0, 50, 50);
        if(map[x+1][y+1][z+1] == 2){
            glRotatef(90, 0.0f, 1.0f, 0.0f);
        }
        if(map[x+1][y+1][z+1] == 1){
            glRotatef(90, 1.0f, 0.0f, 0.0f);
        }

        glBegin(GL_QUAD_STRIP);
            glColor3ub(red, green, blue);
            GLfloat COSan_3 = 0.0;
            GLfloat SINan_3 = 0.0;
            for(GLfloat an = 0.0; an <= 2.0 * M_PI; an += M_PI / 12.0) {
                        glNormal3f((COSan_3 = cos(an)/3.0), (SINan_3 = sin(an)/3.0), 2.0);
                        glVertex3f(COSan_3, SINan_3, 0.5f);
                        glVertex3f(COSan_3, SINan_3, -0.5f);
        }
        glEnd();
    }
    for(unsigned int b = 0; b < part_coords2.size(); b++){
        glLoadIdentity();

        x = part_coords2[b][0];
        y = part_coords2[b][1];
        z = part_coords2[b][2];

        glTranslatef(x-(WIDTH+15)/2, -y+(HEIGHT+1)/2, z-2*DEPTH);

        if(map2[x+1][y+1][z+1] == 2){
            glRotatef(90, 0.0f, 1.0f, 0.0f);
        }
        if(map2[x+1][y+1][z+1] == 1){
            glRotatef(90, 1.0f, 0.0f, 0.0f);
        }

        glBegin(GL_QUAD_STRIP);
            glColor3ub(color.at(b)[0], color.at(b)[1], color.at(b)[2]);
            GLfloat COSan_3 = 0.0;
            GLfloat SINan_3 = 0.0;
            for(GLfloat an = 0.0; an <= 2.0 * M_PI; an += M_PI / 12.0) {
                        glNormal3f((COSan_3 = cos(an)/3.0), (SINan_3 = sin(an)/3.0), 2.0);
                        glVertex3f(COSan_3, SINan_3, 0.5f);
                        glVertex3f(COSan_3, SINan_3, -0.5f);
            }
        glEnd();
    }
    glutSwapBuffers();
}
<|endoftext|>


<commit_before>/*
** Copyright 1994 by Miron Livny, and Mike Litzkow
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted,
** provided that the above copyright notice appear in all copies and that
** both that copyright notice and this permission notice appear in
** supporting documentation, and that the names of the University of
** Wisconsin and the copyright holders not be used in advertising or
** publicity pertaining to distribution of the software without specific,
** written prior permission.  The University of Wisconsin and the
** copyright holders make no representations about the suitability of this
** software for any purpose.  It is provided "as is" without express
** or implied warranty.
**
** THE UNIVERSITY OF WISCONSIN AND THE COPYRIGHT HOLDERS DISCLAIM ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE UNIVERSITY OF
** WISCONSIN OR THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT
** OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
** OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
** OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
** OR PERFORMANCE OF THIS SOFTWARE.
**
** Author:  Mike Litzkow
**
*/

#define _POSIX_SOURCE

#if defined(IRIX62)
typedef struct fd_set fd_set;
#endif

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include "image.h"

void test_func();

int		GlobalDataObj;
long	SomeDataAddr = (long)&GlobalDataObj;

void
Suicide()
{
	exit(1);
}

int
main( int argc, char *argv )
{
	int		local_data_obj;
	long	some_stack_addr = (long)&local_data_obj;
	long	data_start, data_end;
	long	stack_start, stack_end;

	data_start = data_start_addr();
	data_end = data_end_addr();
	stack_start = stack_start_addr();
	stack_end = stack_end_addr();

	fprintf( stderr, "Data starts at 0x%lX\n", data_start );
	fprintf( stderr, "Data ends at 0x%lX\n", data_end );
	fprintf( stderr, "Typical Data addr at 0x%lX\n", SomeDataAddr );
	assert( data_start < data_end );
	assert( data_start < SomeDataAddr && SomeDataAddr < data_end );

	fprintf( stderr, "Stack starts at 0x%lX\n", stack_start );
	fprintf( stderr, "Stack ends at 0x%lX\n", stack_end );
	fprintf( stderr, "Typical Stack addr at 0x%lX\n", some_stack_addr );
	assert( stack_start < stack_end );
	assert( stack_start < some_stack_addr && some_stack_addr < stack_end );

	fprintf( stderr, "Stack grows %s\n", StackGrowsDown() ? "DOWN" : "UP" );
	fprintf( stderr, "Index of Stack Pointer in jmp_buf is %d\n", JmpBufSP_Index() );
	ExecuteOnTmpStk( test_func );

	fprintf( stderr, "ERROR test_func() returned\n" );
	return 1;
}

void
test_func()
{
	int		i;

	fprintf( stderr, "This should be a DATA address 0x%lX\n", &i );
	exit( 0 );
}
extern "C"
SetSyscalls( int mode )
{
}
<commit_msg>Modified to use condor_common.h now.<commit_after>/*
** Copyright 1994 by Miron Livny, and Mike Litzkow
**
** Permission to use, copy, modify, and distribute this software and its
** documentation for any purpose and without fee is hereby granted,
** provided that the above copyright notice appear in all copies and that
** both that copyright notice and this permission notice appear in
** supporting documentation, and that the names of the University of
** Wisconsin and the copyright holders not be used in advertising or
** publicity pertaining to distribution of the software without specific,
** written prior permission.  The University of Wisconsin and the
** copyright holders make no representations about the suitability of this
** software for any purpose.  It is provided "as is" without express
** or implied warranty.
**
** THE UNIVERSITY OF WISCONSIN AND THE COPYRIGHT HOLDERS DISCLAIM ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE UNIVERSITY OF
** WISCONSIN OR THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT
** OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
** OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
** OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
** OR PERFORMANCE OF THIS SOFTWARE.
**
** Author:  Mike Litzkow
**
*/

#include "condor_common.h"
#include "image.h"

void test_func();

int		GlobalDataObj;
long	SomeDataAddr = (long)&GlobalDataObj;

void
Suicide()
{
	exit(1);
}

int
main( int argc, char *argv )
{
	int		local_data_obj;
	long	some_stack_addr = (long)&local_data_obj;
	long	data_start, data_end;
	long	stack_start, stack_end;

	data_start = data_start_addr();
	data_end = data_end_addr();
	stack_start = stack_start_addr();
	stack_end = stack_end_addr();

	fprintf( stderr, "Data starts at 0x%lX\n", data_start );
	fprintf( stderr, "Data ends at 0x%lX\n", data_end );
	fprintf( stderr, "Typical Data addr at 0x%lX\n", SomeDataAddr );
	assert( data_start < data_end );
	assert( data_start < SomeDataAddr && SomeDataAddr < data_end );

	fprintf( stderr, "Stack starts at 0x%lX\n", stack_start );
	fprintf( stderr, "Stack ends at 0x%lX\n", stack_end );
	fprintf( stderr, "Typical Stack addr at 0x%lX\n", some_stack_addr );
	assert( stack_start < stack_end );
	assert( stack_start < some_stack_addr && some_stack_addr < stack_end );

	fprintf( stderr, "Stack grows %s\n", StackGrowsDown() ? "DOWN" : "UP" );
	fprintf( stderr, "Index of Stack Pointer in jmp_buf is %d\n", JmpBufSP_Index() );
	ExecuteOnTmpStk( test_func );

	fprintf( stderr, "ERROR test_func() returned\n" );
	return 1;
}

void
test_func()
{
	int		i;

	fprintf( stderr, "This should be a DATA address 0x%lX\n", &i );
	exit( 0 );
}
extern "C"
SetSyscalls( int mode )
{
}
<|endoftext|>


<commit_before>#ifndef __FENWICK_BITF_HPP__
#define __FENWICK_BITF_HPP__

#include "fenwick_tree.hpp"

namespace hft::fenwick {

/**
 * class BitF - bit compression and classical node layout.
 * @sequence: sequence of integers.
 * @size: number of elements.
 * @BOUND: maximum value that @sequence can store.
 *
 */
template <size_t BOUND> class BitF : public FenwickTree {
public:
  static constexpr size_t BOUNDSIZE = ceil_log2_plus1(BOUND);
  static constexpr size_t STARTING_OFFSET = 1;
  static constexpr size_t END_PADDING = 56;
  static_assert(BOUNDSIZE >= 1 && BOUNDSIZE <= 55, "Some nodes will span on multiple words");

protected:
  size_t Size;
  DArray<uint8_t> Tree;

public:
  BitF(uint64_t sequence[], size_t size)
      : Size(size), Tree((first_bit_after(size) + END_PADDING + 7) >> 3) {
    for (size_t idx = 1; idx <= size; idx++)
      addToPartialFrequency(idx, sequence[idx - 1]);

    for (size_t m = 2; m <= size; m <<= 1)
      for (size_t idx = m; idx <= size; idx += m)
        addToPartialFrequency(idx, getPartialFrequency(idx - m / 2));
  }

  virtual uint64_t prefix(size_t idx) const {
    uint64_t sum = 0;

    while (idx != 0) {
      sum += getPartialFrequency(idx);
      idx = clear_rho(idx);
    }

    return sum;
  }

  virtual void add(size_t idx, int64_t inc) {
    while (idx <= Size) {
      addToPartialFrequency(idx, inc);
      idx += mask_rho(idx);
    }
  }

  using FenwickTree::find;
  virtual size_t find(uint64_t *val) const {
    size_t node = 0;

    for (size_t m = mask_lambda(Size); m != 0; m >>= 1) {
      if (node + m > Size)
        continue;

      const uint64_t value = getPartialFrequency(node + m);

      if (*val >= value) {
        node += m;
        *val -= value;
      }
    }

    return node;
  }

  using FenwickTree::compFind;
  virtual size_t compFind(uint64_t *val) const {
    size_t node = 0;

    for (size_t m = mask_lambda(Size); m != 0; m >>= 1) {
      if (node + m > Size)
        continue;

      const int height = rho(node + m);
      const uint64_t value = (BOUND << height) - getPartialFrequency(node + m);

      if (*val >= value) {
        node += m;
        *val -= value;
      }
    }

    return node;
  }

  virtual size_t size() const { return Size; }

  virtual size_t bitCount() const {
    return sizeof(BitF<BOUNDSIZE>) * 8 + Tree.bitCount() - sizeof(Tree);
  }

private:
  inline static size_t holes(size_t idx) { return STARTING_OFFSET + (idx >> 14) * 64; }

  inline static size_t first_bit_after(size_t idx) {
    return (BOUNDSIZE + 1) * idx - popcount(idx) + holes(idx);
  }

  inline uint64_t getPartialFrequency(size_t idx) const {
    const uint64_t mask = (UINT64_C(1) << (BOUNDSIZE + rho(idx))) - 1;
    idx--;
    const uint64_t prod = (BOUNDSIZE + 1) * idx;
    const size_t pos = prod - popcount(idx) + holes(idx);

    return (prod + (BOUNDSIZE + 1)) % 64 == 0
               ? (*(reinterpret_cast<auint64_t *>(&Tree[0]) + pos / 64) >> (pos % 64)) & mask
               : (*(reinterpret_cast<auint64_t *>(&Tree[pos / 8])) >> (pos % 8)) & mask;
  }

  inline void addToPartialFrequency(size_t idx, uint64_t value) {
    idx--;
    const size_t prod = (BOUNDSIZE + 1) * idx;
    const size_t pos = prod - popcount(idx) + holes(idx);

    if ((prod + (BOUNDSIZE + 1)) % 64 == 0) *(reinterpret_cast<auint64_t *>(&Tree[0]) + pos / 64) += value << (pos % 64);
    else *reinterpret_cast<auint64_t *>(&Tree[pos / 8]) += value << (pos % 8);
  }

  friend std::ostream &operator<<(std::ostream &os, const BitF<BOUND> &ft) {
    const uint64_t nsize = hton((uint64_t)ft.Size);
    os.write((char *)&nsize, sizeof(uint64_t));

    return os << ft.Tree;
  }

  friend std::istream &operator>>(std::istream &is, BitF<BOUND> &ft) {
    uint64_t nsize;
    is.read((char *)(&nsize), sizeof(uint64_t));
    ft.Size = ntoh(nsize);

    return is >> ft.Tree;
  }
};

} // namespace hft::fenwick

#endif // __FENWICK_BITF_HPP__
<commit_msg>Now we use memcpy()<commit_after>#ifndef __FENWICK_BITF_HPP__
#define __FENWICK_BITF_HPP__
#include <cstring>
#include "fenwick_tree.hpp"

namespace hft::fenwick {

/**
 * class BitF - bit compression and classical node layout.
 * @sequence: sequence of integers.
 * @size: number of elements.
 * @BOUND: maximum value that @sequence can store.
 *
 */
template <size_t BOUND> class BitF : public FenwickTree {
public:
  static constexpr size_t BOUNDSIZE = ceil_log2_plus1(BOUND);
  static constexpr size_t STARTING_OFFSET = 1;
  static constexpr size_t END_PADDING = 56;
  static_assert(BOUNDSIZE >= 1 && BOUNDSIZE <= 55, "Some nodes will span on multiple words");

protected:
  size_t Size;
  DArray<uint8_t> Tree;

public:
  BitF(uint64_t sequence[], size_t size)
      : Size(size), Tree((first_bit_after(size) + END_PADDING + 7) >> 3) {
    for (size_t idx = 1; idx <= size; idx++)
      addToPartialFrequency(idx, sequence[idx - 1]);

    for (size_t m = 2; m <= size; m <<= 1)
      for (size_t idx = m; idx <= size; idx += m)
        addToPartialFrequency(idx, getPartialFrequency(idx - m / 2));
  }

  virtual uint64_t prefix(size_t idx) const {
    uint64_t sum = 0;

    while (idx != 0) {
      sum += getPartialFrequency(idx);
      idx = clear_rho(idx);
    }

    return sum;
  }

  virtual void add(size_t idx, int64_t inc) {
    while (idx <= Size) {
      addToPartialFrequency(idx, inc);
      idx += mask_rho(idx);
    }
  }

  using FenwickTree::find;
  virtual size_t find(uint64_t *val) const {
    size_t node = 0;

    for (size_t m = mask_lambda(Size); m != 0; m >>= 1) {
      if (node + m > Size)
        continue;

      const uint64_t value = getPartialFrequency(node + m);

      if (*val >= value) {
        node += m;
        *val -= value;
      }
    }

    return node;
  }

  using FenwickTree::compFind;
  virtual size_t compFind(uint64_t *val) const {
    size_t node = 0;

    for (size_t m = mask_lambda(Size); m != 0; m >>= 1) {
      if (node + m > Size)
        continue;

      const int height = rho(node + m);
      const uint64_t value = (BOUND << height) - getPartialFrequency(node + m);

      if (*val >= value) {
        node += m;
        *val -= value;
      }
    }

    return node;
  }

  virtual size_t size() const { return Size; }

  virtual size_t bitCount() const {
    return sizeof(BitF<BOUNDSIZE>) * 8 + Tree.bitCount() - sizeof(Tree);
  }

private:
  inline static size_t holes(size_t idx) { return STARTING_OFFSET + (idx >> 14) * 64; }

  inline static size_t first_bit_after(size_t idx) {
    return (BOUNDSIZE + 1) * idx - popcount(idx) + holes(idx);
  }

  inline uint64_t getPartialFrequency(size_t idx) const {
    const uint64_t mask = (UINT64_C(1) << (BOUNDSIZE + rho(idx))) - 1;
    idx--;
    const uint64_t prod = (BOUNDSIZE + 1) * idx;
    const uint64_t pos = prod - popcount(idx) + holes(idx);

    uint64_t t;
    if ((prod + (BOUNDSIZE + 1)) % 64 == 0) {
        memcpy(&t, (uint64_t *)&Tree[0] + pos / 64, 8);
        return t >> (pos % 64) & mask;
    } else {
        memcpy(&t, &Tree[0] + pos / 8, 8);
        return t >> (pos % 8) & mask;
    }
  }

  inline void addToPartialFrequency(size_t idx, uint64_t value) {
    idx--;
    const uint64_t prod = (BOUNDSIZE + 1) * idx;
    const uint64_t pos = prod - popcount(idx) + holes(idx);

    uint64_t t;
    if ((prod + (BOUNDSIZE + 1)) % 64 == 0) {
        uint64_t * const p = (uint64_t *)&Tree[0] + pos / 64;
        memcpy(&t, p, 8);
        t += value << (pos % 64);
        memcpy(p, &t, 8);
    } else {
        uint8_t * const p = &Tree[0] + pos / 8;
        memcpy(&t, p, 8);
        t += value << (pos % 8);
        memcpy(p, &t, 8);
    }
  }

  friend std::ostream &operator<<(std::ostream &os, const BitF<BOUND> &ft) {
    const uint64_t nsize = hton((uint64_t)ft.Size);
    os.write((char *)&nsize, sizeof(uint64_t));

    return os << ft.Tree;
  }

  friend std::istream &operator>>(std::istream &is, BitF<BOUND> &ft) {
    uint64_t nsize;
    is.read((char *)(&nsize), sizeof(uint64_t));
    ft.Size = ntoh(nsize);

    return is >> ft.Tree;
  }
};

} // namespace hft::fenwick

#endif // __FENWICK_BITF_HPP__
<|endoftext|>


<commit_before>// Copyright (C) 2015 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "CompileConfig.h"

#if defined(OUZEL_PLATFORM_OSX) || defined(OUZEL_PLATFORM_IOS) || defined(OUZEL_PLATFORM_TVOS)
#include <sys/time.h>
#endif

#if defined(OUZEL_PLATFORM_IOS) || defined(OUZEL_PLATFORM_TVOS)
#include <sys/syslog.h>
#endif

#ifdef OUZEL_PLATFORM_WINDOWS
#include <windows.h>
#include <strsafe.h>
#endif

#ifdef OUZEL_PLATFORM_ANDROID
#include <android/log.h>
#endif

#include "Utils.h"

namespace ouzel
{
    char TEMP_BUFFER[65536];

    void log(const char* format, ...)
    {
        char strBuffer[512];

        va_list list;
        va_start(list, format);

        vsprintf(strBuffer, format, list);

        va_end(list);

#if defined(OUZEL_PLATFORM_OSX)
        printf("%s\n", strBuffer);
#elif defined(OUZEL_PLATFORM_IOS) || defined(OUZEL_PLATFORM_TVOS)
        syslog(LOG_WARNING, "%s", strBuffer);
        printf("%s\n", strBuffer);
#elif defined(OUZEL_PLATFORM_WINDOWS)
        wchar_t szBuffer[256];
        MultiByteToWideChar(CP_ACP, 0, strBuffer, -1, szBuffer, 256);
        StringCchCat(szBuffer, sizeof(szBuffer), L"\n");
        OutputDebugString(szBuffer);
#elif defined(OUZEL_PLATFORM_ANDROID)
        __android_log_print(ANDROID_LOG_DEBUG, "Ouzel", "%s", strBuffer);
#endif
    }

    uint64_t getCurrentMicroSeconds()
    {
#if defined(OUZEL_PLATFORM_OSX) || defined(OUZEL_PLATFORM_IOS) || defined(OUZEL_PLATFORM_TVOS) || defined(OUZEL_PLATFORM_ANDROID)
        struct timeval currentTime;

        gettimeofday(&currentTime, NULL);
        return currentTime.tv_sec * 1000000L + currentTime.tv_usec;
#elif defined(OUZEL_PLATFORM_WINDOWS)
        LARGE_INTEGER li;
        if (!QueryPerformanceFrequency(&li))
        {
            log("Failed to query frequency");
            return 0;
        }
        uint64_t frequency = li.QuadPart / 1000000L;

        QueryPerformanceCounter(&li);

        return li.QuadPart / frequency;
#else
        return 0;
#endif
    }
}
<commit_msg>Use TEMP_BUFFER for logging<commit_after>// Copyright (C) 2015 Elviss Strazdins
// This file is part of the Ouzel engine.

#include "CompileConfig.h"

#if defined(OUZEL_PLATFORM_OSX) || defined(OUZEL_PLATFORM_IOS) || defined(OUZEL_PLATFORM_TVOS)
#include <sys/time.h>
#endif

#if defined(OUZEL_PLATFORM_IOS) || defined(OUZEL_PLATFORM_TVOS)
#include <sys/syslog.h>
#endif

#ifdef OUZEL_PLATFORM_WINDOWS
#include <windows.h>
#include <strsafe.h>
#endif

#ifdef OUZEL_PLATFORM_ANDROID
#include <android/log.h>
#endif

#include "Utils.h"

namespace ouzel
{
    char TEMP_BUFFER[65536];

    void log(const char* format, ...)
    {
        va_list list;
        va_start(list, format);

        vsprintf(TEMP_BUFFER, format, list);

        va_end(list);

#if defined(OUZEL_PLATFORM_OSX)
        printf("%s\n", TEMP_BUFFER);
#elif defined(OUZEL_PLATFORM_IOS) || defined(OUZEL_PLATFORM_TVOS)
        syslog(LOG_WARNING, "%s", TEMP_BUFFER);
        printf("%s\n", TEMP_BUFFER);
#elif defined(OUZEL_PLATFORM_WINDOWS)
        wchar_t szBuffer[256];
        MultiByteToWideChar(CP_ACP, 0, TEMP_BUFFER, -1, szBuffer, 256);
        StringCchCat(szBuffer, sizeof(szBuffer), L"\n");
        OutputDebugString(szBuffer);
#elif defined(OUZEL_PLATFORM_ANDROID)
        __android_log_print(ANDROID_LOG_DEBUG, "Ouzel", "%s", TEMP_BUFFER);
#endif
    }

    uint64_t getCurrentMicroSeconds()
    {
#if defined(OUZEL_PLATFORM_OSX) || defined(OUZEL_PLATFORM_IOS) || defined(OUZEL_PLATFORM_TVOS) || defined(OUZEL_PLATFORM_ANDROID)
        struct timeval currentTime;

        gettimeofday(&currentTime, NULL);
        return currentTime.tv_sec * 1000000L + currentTime.tv_usec;
#elif defined(OUZEL_PLATFORM_WINDOWS)
        LARGE_INTEGER li;
        if (!QueryPerformanceFrequency(&li))
        {
            log("Failed to query frequency");
            return 0;
        }
        uint64_t frequency = li.QuadPart / 1000000L;

        QueryPerformanceCounter(&li);

        return li.QuadPart / frequency;
#else
        return 0;
#endif
    }
}
<|endoftext|>


<commit_before>/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap
 *
 * Copyright 2012 Matthew McCormick
 * Copyright 2013 Justin Crawford <Justasic@gmail.com>
 * Copyright 2015 Pawel 'l0ner' Soltys
 *
 * 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.
 */

// Based on: github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c
// Based on: Apple.cpp for load_string/mem_string and apple's documentation

#include <sys/types.h>
#include <unistd.h> // usleep

#include "getsysctl.h"
#include "cpu.h"

uint8_t get_cpu_count()
{
  int32_t cpu_count = 0;
  GETSYSCTL( "hw.ncpu", cpu_count );

  return static_cast<uint8_t>( cpu_count );
}

float cpu_percentage( unsigned int cpu_usage_delay )
{
  u_long load1[CP_STATES];
  u_long load2[CP_STATES];

  GETSYSCTL( "kern.cp_time", load1 );
  usleep( cpu_usage_delay );
  GETSYSCTL( "kern.cp_time", load2 );

  // Current load times
  unsigned long long current_user = load1[CP_USER];
  unsigned long long current_system = load1[CP_SYS];
  unsigned long long current_nice = load1[CP_NICE];
  unsigned long long current_idle = load1[CP_IDLE];
  // Next load times
  unsigned long long next_user = load2[CP_USER];
  unsigned long long next_system = load2[CP_SYS];
  unsigned long long next_nice = load2[CP_NICE];
  unsigned long long next_idle = load2[CP_IDLE];
  // Difference between the two
  unsigned long long diff_user = next_user - current_user;
  unsigned long long diff_system = next_system - current_system;
  unsigned long long diff_nice = next_nice - current_nice;
  unsigned long long diff_idle = next_idle - current_idle;

  return static_cast<float>( diff_user + diff_system + diff_nice ) /
    static_cast<float>( diff_user + diff_system + diff_nice + diff_idle ) *
    100.0;
}
<commit_msg>Consistent get_cpu_count for FreeBSD<commit_after>/* vim: tabstop=2 shiftwidth=2 expandtab textwidth=80 linebreak wrap
 *
 * Copyright 2012 Matthew McCormick
 * Copyright 2013 Justin Crawford <Justasic@gmail.com>
 * Copyright 2015 Pawel 'l0ner' Soltys
 *
 * 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.
 */

// Based on: github.com/freebsd/freebsd/blob/master/usr.bin/top/machine.c
// Based on: Apple.cpp for load_string/mem_string and apple's documentation

#include <sys/types.h>
#include <unistd.h> // usleep

#include "getsysctl.h"
#include "cpu.h"

uint32_t get_cpu_count()
{
  int32_t cpu_count = 0;
  GETSYSCTL( "hw.ncpu", cpu_count );

  return static_cast<uint32_t>( cpu_count );
}

float cpu_percentage( unsigned int cpu_usage_delay )
{
  u_long load1[CP_STATES];
  u_long load2[CP_STATES];

  GETSYSCTL( "kern.cp_time", load1 );
  usleep( cpu_usage_delay );
  GETSYSCTL( "kern.cp_time", load2 );

  // Current load times
  unsigned long long current_user = load1[CP_USER];
  unsigned long long current_system = load1[CP_SYS];
  unsigned long long current_nice = load1[CP_NICE];
  unsigned long long current_idle = load1[CP_IDLE];
  // Next load times
  unsigned long long next_user = load2[CP_USER];
  unsigned long long next_system = load2[CP_SYS];
  unsigned long long next_nice = load2[CP_NICE];
  unsigned long long next_idle = load2[CP_IDLE];
  // Difference between the two
  unsigned long long diff_user = next_user - current_user;
  unsigned long long diff_system = next_system - current_system;
  unsigned long long diff_nice = next_nice - current_nice;
  unsigned long long diff_idle = next_idle - current_idle;

  return static_cast<float>( diff_user + diff_system + diff_nice ) /
    static_cast<float>( diff_user + diff_system + diff_nice + diff_idle ) *
    100.0;
}
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2015 gRPC authors.
 *
 * 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 <grpc/support/port_platform.h>

#include "src/core/lib/iomgr/executor.h"

#include <string.h>
#include <functional>

#include <grpc/support/alloc.h>
#include <grpc/support/cpu.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>

#include "src/core/lib/debug/stats.h"
#include "src/core/lib/gpr/tls.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/iomgr/exec_ctx.h"

#define MAX_DEPTH 2

#define EXECUTOR_TRACE(format, ...)                     \
  if (executor_trace.enabled()) {                       \
    gpr_log(GPR_INFO, "EXECUTOR " format, __VA_ARGS__); \
  }

grpc_core::TraceFlag executor_trace(false, "executor");

GPR_TLS_DECL(g_this_thread_state);

GrpcExecutor::GrpcExecutor(const char* executor_name) : name_(executor_name) {
  adding_thread_lock_ = GPR_SPINLOCK_STATIC_INITIALIZER;
  gpr_atm_no_barrier_store(&num_threads_, 0);
  max_threads_ = GPR_MAX(1, 2 * gpr_cpu_num_cores());
}

void GrpcExecutor::Init() { SetThreading(true); }

size_t GrpcExecutor::RunClosures(grpc_closure_list list) {
  size_t n = 0;

  grpc_closure* c = list.head;
  while (c != nullptr) {
    grpc_closure* next = c->next_data.next;
    grpc_error* error = c->error_data.error;
#ifndef NDEBUG
    EXECUTOR_TRACE("run %p [created by %s:%d]", c, c->file_created,
                   c->line_created);
    c->scheduled = false;
#else
    EXECUTOR_TRACE("run %p", c);
#endif
    c->cb(c->cb_arg, error);
    GRPC_ERROR_UNREF(error);
    c = next;
    n++;
    grpc_core::ExecCtx::Get()->Flush();
  }

  return n;
}

bool GrpcExecutor::IsThreaded() const {
  return gpr_atm_no_barrier_load(&num_threads_) > 0;
}

void GrpcExecutor::SetThreading(bool threading) {
  gpr_atm curr_num_threads = gpr_atm_no_barrier_load(&num_threads_);

  if (threading) {
    if (curr_num_threads > 0) return;

    GPR_ASSERT(num_threads_ == 0);
    gpr_atm_no_barrier_store(&num_threads_, 1);
    gpr_tls_init(&g_this_thread_state);
    thd_state_ = static_cast<ThreadState*>(
        gpr_zalloc(sizeof(ThreadState) * max_threads_));

    for (size_t i = 0; i < max_threads_; i++) {
      gpr_mu_init(&thd_state_[i].mu);
      gpr_cv_init(&thd_state_[i].cv);
      thd_state_[i].id = i;
      thd_state_[i].thd = grpc_core::Thread();
      thd_state_[i].elems = GRPC_CLOSURE_LIST_INIT;
    }

    thd_state_[0].thd =
        grpc_core::Thread(name_, &GrpcExecutor::ThreadMain, &thd_state_[0]);
    thd_state_[0].thd.Start();
  } else {  // !threading
    if (curr_num_threads == 0) return;

    for (size_t i = 0; i < max_threads_; i++) {
      gpr_mu_lock(&thd_state_[i].mu);
      thd_state_[i].shutdown = true;
      gpr_cv_signal(&thd_state_[i].cv);
      gpr_mu_unlock(&thd_state_[i].mu);
    }

    /* Ensure no thread is adding a new thread. Once this is past, then no
     * thread will try to add a new one either (since shutdown is true) */
    gpr_spinlock_lock(&adding_thread_lock_);
    gpr_spinlock_unlock(&adding_thread_lock_);

    curr_num_threads = gpr_atm_no_barrier_load(&num_threads_);
    for (gpr_atm i = 0; i < curr_num_threads; i++) {
      thd_state_[i].thd.Join();
      EXECUTOR_TRACE(" Thread %" PRIdPTR " of %" PRIdPTR " joined", i,
                     curr_num_threads);
    }

    gpr_atm_no_barrier_store(&num_threads_, 0);
    for (size_t i = 0; i < max_threads_; i++) {
      gpr_mu_destroy(&thd_state_[i].mu);
      gpr_cv_destroy(&thd_state_[i].cv);
      RunClosures(thd_state_[i].elems);
    }

    gpr_free(thd_state_);
    gpr_tls_destroy(&g_this_thread_state);
  }
}

void GrpcExecutor::Shutdown() { SetThreading(false); }

void GrpcExecutor::ThreadMain(void* arg) {
  ThreadState* ts = static_cast<ThreadState*>(arg);
  gpr_tls_set(&g_this_thread_state, reinterpret_cast<intptr_t>(ts));

  grpc_core::ExecCtx exec_ctx(GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD);

  size_t subtract_depth = 0;
  for (;;) {
    EXECUTOR_TRACE("[%" PRIdPTR "]: step (sub_depth=%" PRIdPTR ")", ts->id,
                   subtract_depth);

    gpr_mu_lock(&ts->mu);
    ts->depth -= subtract_depth;
    // Wait for closures to be enqueued or for the executor to be shutdown
    while (grpc_closure_list_empty(ts->elems) && !ts->shutdown) {
      ts->queued_long_job = false;
      gpr_cv_wait(&ts->cv, &ts->mu, gpr_inf_future(GPR_CLOCK_MONOTONIC));
    }

    if (ts->shutdown) {
      EXECUTOR_TRACE("[%" PRIdPTR "]: shutdown", ts->id);
      gpr_mu_unlock(&ts->mu);
      break;
    }

    GRPC_STATS_INC_EXECUTOR_QUEUE_DRAINED();
    grpc_closure_list closures = ts->elems;
    ts->elems = GRPC_CLOSURE_LIST_INIT;
    gpr_mu_unlock(&ts->mu);

    EXECUTOR_TRACE("[%" PRIdPTR "]: execute", ts->id);

    grpc_core::ExecCtx::Get()->InvalidateNow();
    subtract_depth = RunClosures(closures);
  }
}

void GrpcExecutor::Enqueue(grpc_closure* closure, grpc_error* error,
                           bool is_short) {
  bool retry_push;
  if (is_short) {
    GRPC_STATS_INC_EXECUTOR_SCHEDULED_SHORT_ITEMS();
  } else {
    GRPC_STATS_INC_EXECUTOR_SCHEDULED_LONG_ITEMS();
  }

  do {
    retry_push = false;
    size_t cur_thread_count =
        static_cast<size_t>(gpr_atm_no_barrier_load(&num_threads_));

    // If the number of threads is zero(i.e either the executor is not threaded
    // or already shutdown), then queue the closure on the exec context itself
    if (cur_thread_count == 0) {
#ifndef NDEBUG
      EXECUTOR_TRACE("schedule %p (created %s:%d) inline", closure,
                     closure->file_created, closure->line_created);
#else
      EXECUTOR_TRACE("schedule %p inline", closure);
#endif
      grpc_closure_list_append(grpc_core::ExecCtx::Get()->closure_list(),
                               closure, error);
      return;
    }

    ThreadState* ts = (ThreadState*)gpr_tls_get(&g_this_thread_state);
    if (ts == nullptr) {
      ts = &thd_state_[GPR_HASH_POINTER(grpc_core::ExecCtx::Get(),
                                        cur_thread_count)];
    } else {
      GRPC_STATS_INC_EXECUTOR_SCHEDULED_TO_SELF();
    }

    ThreadState* orig_ts = ts;

    bool try_new_thread = false;
    for (;;) {
#ifndef NDEBUG
      EXECUTOR_TRACE(
          "try to schedule %p (%s) (created %s:%d) to thread "
          "%" PRIdPTR,
          closure, is_short ? "short" : "long", closure->file_created,
          closure->line_created, ts->id);
#else
      EXECUTOR_TRACE("try to schedule %p (%s) to thread %" PRIdPTR, closure,
                     is_short ? "short" : "long", ts->id);
#endif

      gpr_mu_lock(&ts->mu);
      if (ts->queued_long_job) {
        // if there's a long job queued, we never queue anything else to this
        // queue (since long jobs can take 'infinite' time and we need to
        // guarantee no starvation). Spin through queues and try again
        gpr_mu_unlock(&ts->mu);
        size_t idx = ts->id;
        ts = &thd_state_[(idx + 1) % cur_thread_count];
        if (ts == orig_ts) {
          // We cycled through all the threads. Retry enqueue again (by creating
          // a new thread)
          retry_push = true;
          // TODO (sreek): What if the executor is shutdown OR if
          // cur_thread_count is already equal to max_threads ? (currently - as
          // of July 2018, we do not run in to this issue because there is only
          // one instance of long job in gRPC. This has to be fixed soon)
          try_new_thread = true;
          break;
        }

        continue;
      }

      // == Found the thread state (i.e thread) to enqueue this closure! ==

      // Also, if this thread has been waiting for closures, wake it up.
      // - If grpc_closure_list_empty() is true and the Executor is not
      //   shutdown, it means that the thread must be waiting in ThreadMain()
      // - Note that gpr_cv_signal() won't immediately wakeup the thread. That
      //   happens after we release the mutex &ts->mu a few lines below
      if (grpc_closure_list_empty(ts->elems) && !ts->shutdown) {
        GRPC_STATS_INC_EXECUTOR_WAKEUP_INITIATED();
        gpr_cv_signal(&ts->cv);
      }

      grpc_closure_list_append(&ts->elems, closure, error);

      // If we already queued more than MAX_DEPTH number of closures on this
      // thread, use this as a hint to create more threads
      ts->depth++;
      try_new_thread = ts->depth > MAX_DEPTH &&
                       cur_thread_count < max_threads_ && !ts->shutdown;

      ts->queued_long_job = !is_short;

      gpr_mu_unlock(&ts->mu);
      break;
    }

    if (try_new_thread && gpr_spinlock_trylock(&adding_thread_lock_)) {
      cur_thread_count =
          static_cast<size_t>(gpr_atm_no_barrier_load(&num_threads_));
      if (cur_thread_count < max_threads_) {
        // Increment num_threads (Safe to do a no_barrier_store instead of a
        // cas because we always increment num_threads under the
        // 'adding_thread_lock')
        gpr_atm_no_barrier_store(&num_threads_, cur_thread_count + 1);

        thd_state_[cur_thread_count].thd = grpc_core::Thread(
            name_, &GrpcExecutor::ThreadMain, &thd_state_[cur_thread_count]);
        thd_state_[cur_thread_count].thd.Start();
      }
      gpr_spinlock_unlock(&adding_thread_lock_);
    }

    if (retry_push) {
      GRPC_STATS_INC_EXECUTOR_PUSH_RETRIES();
    }
  } while (retry_push);
}

static GrpcExecutor g_global_executor("grpc-executor");

void enqueue_long(grpc_closure* closure, grpc_error* error) {
  g_global_executor.Enqueue(closure, error, false /* is_short */);
}

void enqueue_short(grpc_closure* closure, grpc_error* error) {
  g_global_executor.Enqueue(closure, error, true /* is_short */);
}

// Short-Job executor scheduler
static const grpc_closure_scheduler_vtable global_executor_vtable_short = {
    enqueue_short, enqueue_short, "executor-short"};
static grpc_closure_scheduler global_scheduler_short = {
    &global_executor_vtable_short};

// Long-job executor scheduler
static const grpc_closure_scheduler_vtable global_executor_vtable_long = {
    enqueue_long, enqueue_long, "executor-long"};
static grpc_closure_scheduler global_scheduler_long = {
    &global_executor_vtable_long};

void grpc_executor_init() { g_global_executor.Init(); }

void grpc_executor_shutdown() { g_global_executor.Shutdown(); }

bool grpc_executor_is_threaded() { return g_global_executor.IsThreaded(); }

void grpc_executor_set_threading(bool enable) {
  g_global_executor.SetThreading(enable);
}

grpc_closure_scheduler* grpc_executor_scheduler(GrpcExecutorJobType job_type) {
  return job_type == GRPC_EXECUTOR_SHORT ? &global_scheduler_short
                                         : &global_scheduler_long;
}
<commit_msg>remove unnecessary header<commit_after>/*
 *
 * Copyright 2015 gRPC authors.
 *
 * 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 <grpc/support/port_platform.h>

#include "src/core/lib/iomgr/executor.h"

#include <string.h>

#include <grpc/support/alloc.h>
#include <grpc/support/cpu.h>
#include <grpc/support/log.h>
#include <grpc/support/sync.h>

#include "src/core/lib/debug/stats.h"
#include "src/core/lib/gpr/tls.h"
#include "src/core/lib/gpr/useful.h"
#include "src/core/lib/iomgr/exec_ctx.h"

#define MAX_DEPTH 2

#define EXECUTOR_TRACE(format, ...)                     \
  if (executor_trace.enabled()) {                       \
    gpr_log(GPR_INFO, "EXECUTOR " format, __VA_ARGS__); \
  }

grpc_core::TraceFlag executor_trace(false, "executor");

GPR_TLS_DECL(g_this_thread_state);

GrpcExecutor::GrpcExecutor(const char* executor_name) : name_(executor_name) {
  adding_thread_lock_ = GPR_SPINLOCK_STATIC_INITIALIZER;
  gpr_atm_no_barrier_store(&num_threads_, 0);
  max_threads_ = GPR_MAX(1, 2 * gpr_cpu_num_cores());
}

void GrpcExecutor::Init() { SetThreading(true); }

size_t GrpcExecutor::RunClosures(grpc_closure_list list) {
  size_t n = 0;

  grpc_closure* c = list.head;
  while (c != nullptr) {
    grpc_closure* next = c->next_data.next;
    grpc_error* error = c->error_data.error;
#ifndef NDEBUG
    EXECUTOR_TRACE("run %p [created by %s:%d]", c, c->file_created,
                   c->line_created);
    c->scheduled = false;
#else
    EXECUTOR_TRACE("run %p", c);
#endif
    c->cb(c->cb_arg, error);
    GRPC_ERROR_UNREF(error);
    c = next;
    n++;
    grpc_core::ExecCtx::Get()->Flush();
  }

  return n;
}

bool GrpcExecutor::IsThreaded() const {
  return gpr_atm_no_barrier_load(&num_threads_) > 0;
}

void GrpcExecutor::SetThreading(bool threading) {
  gpr_atm curr_num_threads = gpr_atm_no_barrier_load(&num_threads_);

  if (threading) {
    if (curr_num_threads > 0) return;

    GPR_ASSERT(num_threads_ == 0);
    gpr_atm_no_barrier_store(&num_threads_, 1);
    gpr_tls_init(&g_this_thread_state);
    thd_state_ = static_cast<ThreadState*>(
        gpr_zalloc(sizeof(ThreadState) * max_threads_));

    for (size_t i = 0; i < max_threads_; i++) {
      gpr_mu_init(&thd_state_[i].mu);
      gpr_cv_init(&thd_state_[i].cv);
      thd_state_[i].id = i;
      thd_state_[i].thd = grpc_core::Thread();
      thd_state_[i].elems = GRPC_CLOSURE_LIST_INIT;
    }

    thd_state_[0].thd =
        grpc_core::Thread(name_, &GrpcExecutor::ThreadMain, &thd_state_[0]);
    thd_state_[0].thd.Start();
  } else {  // !threading
    if (curr_num_threads == 0) return;

    for (size_t i = 0; i < max_threads_; i++) {
      gpr_mu_lock(&thd_state_[i].mu);
      thd_state_[i].shutdown = true;
      gpr_cv_signal(&thd_state_[i].cv);
      gpr_mu_unlock(&thd_state_[i].mu);
    }

    /* Ensure no thread is adding a new thread. Once this is past, then no
     * thread will try to add a new one either (since shutdown is true) */
    gpr_spinlock_lock(&adding_thread_lock_);
    gpr_spinlock_unlock(&adding_thread_lock_);

    curr_num_threads = gpr_atm_no_barrier_load(&num_threads_);
    for (gpr_atm i = 0; i < curr_num_threads; i++) {
      thd_state_[i].thd.Join();
      EXECUTOR_TRACE(" Thread %" PRIdPTR " of %" PRIdPTR " joined", i,
                     curr_num_threads);
    }

    gpr_atm_no_barrier_store(&num_threads_, 0);
    for (size_t i = 0; i < max_threads_; i++) {
      gpr_mu_destroy(&thd_state_[i].mu);
      gpr_cv_destroy(&thd_state_[i].cv);
      RunClosures(thd_state_[i].elems);
    }

    gpr_free(thd_state_);
    gpr_tls_destroy(&g_this_thread_state);
  }
}

void GrpcExecutor::Shutdown() { SetThreading(false); }

void GrpcExecutor::ThreadMain(void* arg) {
  ThreadState* ts = static_cast<ThreadState*>(arg);
  gpr_tls_set(&g_this_thread_state, reinterpret_cast<intptr_t>(ts));

  grpc_core::ExecCtx exec_ctx(GRPC_EXEC_CTX_FLAG_IS_INTERNAL_THREAD);

  size_t subtract_depth = 0;
  for (;;) {
    EXECUTOR_TRACE("[%" PRIdPTR "]: step (sub_depth=%" PRIdPTR ")", ts->id,
                   subtract_depth);

    gpr_mu_lock(&ts->mu);
    ts->depth -= subtract_depth;
    // Wait for closures to be enqueued or for the executor to be shutdown
    while (grpc_closure_list_empty(ts->elems) && !ts->shutdown) {
      ts->queued_long_job = false;
      gpr_cv_wait(&ts->cv, &ts->mu, gpr_inf_future(GPR_CLOCK_MONOTONIC));
    }

    if (ts->shutdown) {
      EXECUTOR_TRACE("[%" PRIdPTR "]: shutdown", ts->id);
      gpr_mu_unlock(&ts->mu);
      break;
    }

    GRPC_STATS_INC_EXECUTOR_QUEUE_DRAINED();
    grpc_closure_list closures = ts->elems;
    ts->elems = GRPC_CLOSURE_LIST_INIT;
    gpr_mu_unlock(&ts->mu);

    EXECUTOR_TRACE("[%" PRIdPTR "]: execute", ts->id);

    grpc_core::ExecCtx::Get()->InvalidateNow();
    subtract_depth = RunClosures(closures);
  }
}

void GrpcExecutor::Enqueue(grpc_closure* closure, grpc_error* error,
                           bool is_short) {
  bool retry_push;
  if (is_short) {
    GRPC_STATS_INC_EXECUTOR_SCHEDULED_SHORT_ITEMS();
  } else {
    GRPC_STATS_INC_EXECUTOR_SCHEDULED_LONG_ITEMS();
  }

  do {
    retry_push = false;
    size_t cur_thread_count =
        static_cast<size_t>(gpr_atm_no_barrier_load(&num_threads_));

    // If the number of threads is zero(i.e either the executor is not threaded
    // or already shutdown), then queue the closure on the exec context itself
    if (cur_thread_count == 0) {
#ifndef NDEBUG
      EXECUTOR_TRACE("schedule %p (created %s:%d) inline", closure,
                     closure->file_created, closure->line_created);
#else
      EXECUTOR_TRACE("schedule %p inline", closure);
#endif
      grpc_closure_list_append(grpc_core::ExecCtx::Get()->closure_list(),
                               closure, error);
      return;
    }

    ThreadState* ts = (ThreadState*)gpr_tls_get(&g_this_thread_state);
    if (ts == nullptr) {
      ts = &thd_state_[GPR_HASH_POINTER(grpc_core::ExecCtx::Get(),
                                        cur_thread_count)];
    } else {
      GRPC_STATS_INC_EXECUTOR_SCHEDULED_TO_SELF();
    }

    ThreadState* orig_ts = ts;

    bool try_new_thread = false;
    for (;;) {
#ifndef NDEBUG
      EXECUTOR_TRACE(
          "try to schedule %p (%s) (created %s:%d) to thread "
          "%" PRIdPTR,
          closure, is_short ? "short" : "long", closure->file_created,
          closure->line_created, ts->id);
#else
      EXECUTOR_TRACE("try to schedule %p (%s) to thread %" PRIdPTR, closure,
                     is_short ? "short" : "long", ts->id);
#endif

      gpr_mu_lock(&ts->mu);
      if (ts->queued_long_job) {
        // if there's a long job queued, we never queue anything else to this
        // queue (since long jobs can take 'infinite' time and we need to
        // guarantee no starvation). Spin through queues and try again
        gpr_mu_unlock(&ts->mu);
        size_t idx = ts->id;
        ts = &thd_state_[(idx + 1) % cur_thread_count];
        if (ts == orig_ts) {
          // We cycled through all the threads. Retry enqueue again (by creating
          // a new thread)
          retry_push = true;
          // TODO (sreek): What if the executor is shutdown OR if
          // cur_thread_count is already equal to max_threads ? (currently - as
          // of July 2018, we do not run in to this issue because there is only
          // one instance of long job in gRPC. This has to be fixed soon)
          try_new_thread = true;
          break;
        }

        continue;
      }

      // == Found the thread state (i.e thread) to enqueue this closure! ==

      // Also, if this thread has been waiting for closures, wake it up.
      // - If grpc_closure_list_empty() is true and the Executor is not
      //   shutdown, it means that the thread must be waiting in ThreadMain()
      // - Note that gpr_cv_signal() won't immediately wakeup the thread. That
      //   happens after we release the mutex &ts->mu a few lines below
      if (grpc_closure_list_empty(ts->elems) && !ts->shutdown) {
        GRPC_STATS_INC_EXECUTOR_WAKEUP_INITIATED();
        gpr_cv_signal(&ts->cv);
      }

      grpc_closure_list_append(&ts->elems, closure, error);

      // If we already queued more than MAX_DEPTH number of closures on this
      // thread, use this as a hint to create more threads
      ts->depth++;
      try_new_thread = ts->depth > MAX_DEPTH &&
                       cur_thread_count < max_threads_ && !ts->shutdown;

      ts->queued_long_job = !is_short;

      gpr_mu_unlock(&ts->mu);
      break;
    }

    if (try_new_thread && gpr_spinlock_trylock(&adding_thread_lock_)) {
      cur_thread_count =
          static_cast<size_t>(gpr_atm_no_barrier_load(&num_threads_));
      if (cur_thread_count < max_threads_) {
        // Increment num_threads (Safe to do a no_barrier_store instead of a
        // cas because we always increment num_threads under the
        // 'adding_thread_lock')
        gpr_atm_no_barrier_store(&num_threads_, cur_thread_count + 1);

        thd_state_[cur_thread_count].thd = grpc_core::Thread(
            name_, &GrpcExecutor::ThreadMain, &thd_state_[cur_thread_count]);
        thd_state_[cur_thread_count].thd.Start();
      }
      gpr_spinlock_unlock(&adding_thread_lock_);
    }

    if (retry_push) {
      GRPC_STATS_INC_EXECUTOR_PUSH_RETRIES();
    }
  } while (retry_push);
}

static GrpcExecutor g_global_executor("grpc-executor");

void enqueue_long(grpc_closure* closure, grpc_error* error) {
  g_global_executor.Enqueue(closure, error, false /* is_short */);
}

void enqueue_short(grpc_closure* closure, grpc_error* error) {
  g_global_executor.Enqueue(closure, error, true /* is_short */);
}

// Short-Job executor scheduler
static const grpc_closure_scheduler_vtable global_executor_vtable_short = {
    enqueue_short, enqueue_short, "executor-short"};
static grpc_closure_scheduler global_scheduler_short = {
    &global_executor_vtable_short};

// Long-job executor scheduler
static const grpc_closure_scheduler_vtable global_executor_vtable_long = {
    enqueue_long, enqueue_long, "executor-long"};
static grpc_closure_scheduler global_scheduler_long = {
    &global_executor_vtable_long};

void grpc_executor_init() { g_global_executor.Init(); }

void grpc_executor_shutdown() { g_global_executor.Shutdown(); }

bool grpc_executor_is_threaded() { return g_global_executor.IsThreaded(); }

void grpc_executor_set_threading(bool enable) {
  g_global_executor.SetThreading(enable);
}

grpc_closure_scheduler* grpc_executor_scheduler(GrpcExecutorJobType job_type) {
  return job_type == GRPC_EXECUTOR_SHORT ? &global_scheduler_short
                                         : &global_scheduler_long;
}
<|endoftext|>