<commit_before>#ifndef ENTT_SIGNAL_SIGH_HPP
#define ENTT_SIGNAL_SIGH_HPP

#include <algorithm>
#include <utility>
#include <vector>
#include <functional>
#include <type_traits>
#include "../config/config.h"
#include "delegate.hpp"
#include "fwd.hpp"

namespace entt {

/**
 * @brief Unmanaged signal handler declaration.
 *
 * Primary template isn't defined on purpose. All the specializations give a
 * compile-time error unless the template parameter is a function type.
 *
 * @tparam Function A valid function type.
 * @tparam Collector Type of collector to use, if any.
 */
template<typename Function>
struct sigh;

/**
 * @brief Sink implementation.
 *
 * Primary template isn't defined on purpose. All the specializations give a
 * compile-time error unless the template parameter is a function type.
 *
 * @tparam Function A valid function type.
 */
template<typename Function>
class sink;

/**
 * @brief Sink implementation.
 *
 * A sink is an opaque object used to connect listeners to signals.

 * The function type for a listener is the one of the signal to which it
 * belongs.
 *
 * The clear separation between a signal and a sink permits to store the former
 * as private data member without exposing the publish functionality to the
 * users of a class.
 *
 * @tparam Ret Return type of a function type.
 * @tparam Args Types of arguments of a function type.
 */
template<typename Ret, typename... Args>
class sink<Ret(Args...)> {
    /*! @brief A signal is allowed to create sinks. */
    template<typename>
    friend struct sigh;

    sink(std::vector<delegate<Ret(Args...)>> *ref) ENTT_NOEXCEPT
        : calls{ref}
    {}

public:
    /**
     * @brief Returns false if at least a listener is connected to the sink.
     * @return True if the sink has no listeners connected, false otherwise.
     */
    bool empty() const ENTT_NOEXCEPT {
        return calls->empty();
    }

    /**
     * @brief Connects a free function to a signal.
     *
     * The signal handler performs checks to avoid multiple connections for free
     * functions.
     *
     * @tparam Function A valid free function pointer.
     */
    template<auto Function>
    void connect() {
        disconnect<Function>();
        delegate<Ret(Args...)> delegate{};
        delegate.template connect<Function>();
        calls->emplace_back(std::move(delegate));
    }

    /**
     * @brief Connects a member function or a free function with payload to a
     * signal.
     *
     * The signal isn't responsible for the connected object or the payload.
     * Users must always guarantee that the lifetime of the instance overcomes
     * the one  of the delegate. On the other side, the signal handler performs
     * checks to avoid multiple connections for the same function.

     * When used to connect a free function with payload, its signature must be
     * such that the instance is the first argument before the ones used to
     * define the delegate itself.
     *
     * @tparam Candidate Member or free function to connect to the signal.
     * @tparam Type Type of class or type of payload.
     * @param value_or_instance A valid pointer that fits the purpose.
     */
    template<auto Candidate, typename Type>
    void connect(Type *value_or_instance) {
        disconnect<Candidate>(value_or_instance);
        delegate<Ret(Args...)> delegate{};
        delegate.template connect<Candidate>(value_or_instance);
        calls->emplace_back(std::move(delegate));
    }

    /**
     * @brief Disconnects a free function from a signal.
     * @tparam Function A valid free function pointer.
     */
    template<auto Function>
    void disconnect() {
        delegate<Ret(Args...)> delegate{};
        delegate.template connect<Function>();
        calls->erase(std::remove(calls->begin(), calls->end(), std::move(delegate)), calls->end());
    }

    /**
     * @brief Disconnects a member function or a free function with payload from
     * a signal.
     * @tparam Candidate Member or free function to disconnect from the signal.
     * @tparam Type Type of class or type of payload.
     * @param value_or_instance A valid pointer that fits the purpose.
     */
    template<auto Candidate, typename Type>
    void disconnect(Type *value_or_instance) {
        delegate<Ret(Args...)> delegate{};
        delegate.template connect<Candidate>(value_or_instance);
        calls->erase(std::remove_if(calls->begin(), calls->end(), [delegate](const auto &other) {
            return other == delegate && other.instance() == delegate.instance();
        }), calls->end());
    }

    /**
     * @brief Disconnects member functions or free functions based on an
     * instance or specific payload.
     * @param value_or_instance A valid pointer that fits the purpose.
     */
    void disconnect(const void *value_or_instance) {
        calls->erase(std::remove_if(calls->begin(), calls->end(), [value_or_instance](const auto &delegate) {
            return value_or_instance == delegate.instance();
        }), calls->end());
    }

    /*! @brief Disconnects all the listeners from a signal. */
    void disconnect() {
        calls->clear();
    }

private:
    std::vector<delegate<Ret(Args...)>> *calls;
};

/**
 * @brief Unmanaged signal handler definition.
 *
 * Unmanaged signal handler. It works directly with naked pointers to classes
 * and pointers to member functions as well as pointers to free functions. Users
 * of this class are in charge of disconnecting instances before deleting them.
 *
 * This class serves mainly two purposes:
 *
 * * Creating signals to use later to notify a bunch of listeners.
 * * Collecting results from a set of functions like in a voting system.
 *
 * @tparam Ret Return type of a function type.
 * @tparam Args Types of arguments of a function type.
 */
template<typename Ret, typename... Args>
struct sigh<Ret(Args...)> {
    /*! @brief Unsigned integer type. */
    using size_type = typename std::vector<delegate<Ret(Args...)>>::size_type;
    /*! @brief Sink type. */
    using sink_type = entt::sink<Ret(Args...)>;

    /**
     * @brief Instance type when it comes to connecting member functions.
     * @tparam Class Type of class to which the member function belongs.
     */
    template<typename Class>
    using instance_type = Class *;

    /**
     * @brief Number of listeners connected to the signal.
     * @return Number of listeners currently connected.
     */
    size_type size() const ENTT_NOEXCEPT {
        return calls.size();
    }

    /**
     * @brief Returns false if at least a listener is connected to the signal.
     * @return True if the signal has no listeners connected, false otherwise.
     */
    bool empty() const ENTT_NOEXCEPT {
        return calls.empty();
    }

    /**
     * @brief Returns a sink object for the given signal.
     *
     * A sink is an opaque object used to connect listeners to signals.

     * The function type for a listener is the one of the signal to which it
     * belongs. The order of invocation of the listeners isn't guaranteed.
     *
     * @return A temporary sink object.
     */
    sink_type sink() ENTT_NOEXCEPT {
        return { &calls };
    }

    /**
     * @brief Triggers a signal.
     *
     * All the listeners are notified. Order isn't guaranteed.
     *
     * @param args Arguments to use to invoke listeners.
     */
    void publish(Args... args) const {
        for(auto pos = calls.size(); pos; --pos) {
            calls[pos-1](args...);
        }
    }

    /**
     * @brief Collects return values from the listeners.
     *
     * The collector must expose a call operator with the following properties:
     *
     * * The return type is either `void` or such that it's convertible to
     *   `bool`. In the second case, a true value will stop the iteration.
     * * The list of parameters is empty if `Ret` is `void`, otherwise it
     *   contains a single element such that `Ret` is convertible to it.
     *
     * @tparam Func Type of collector to use, if any.
     * @param func A valid function object.
     * @param args Arguments to use to invoke listeners.
     */
    template<typename Func>
    void collect(Func func, Args... args) const {
        bool stop = false;

        for(auto pos = calls.size(); pos && !stop; --pos) {
            if constexpr(std::is_void_v<Ret>) {
                if constexpr(std::is_invocable_r_v<bool, Func>) {
                    calls[pos-1](args...);
                    stop = func();
                } else {
                    calls[pos-1](args...);
                    func();
                }
            } else {
                if constexpr(std::is_invocable_r_v<bool, Func, Ret>) {
                    stop = func(calls[pos-1](args...));
                } else {
                    func(calls[pos-1](args...));
                }
            }
        }
    }

    /**
     * @brief Swaps listeners between the two signals.
     * @param lhs A valid signal object.
     * @param rhs A valid signal object.
     */
    friend void swap(sigh &lhs, sigh &rhs) {
        using std::swap;
        swap(lhs.calls, rhs.calls);
    }

private:
    std::vector<delegate<Ret(Args...)>> calls;
};

}

#endif // ENTT_SIGNAL_SIGH_HPP
<commit_msg>cleanup<commit_after>#ifndef ENTT_SIGNAL_SIGH_HPP
#define ENTT_SIGNAL_SIGH_HPP

#include <algorithm>
#include <utility>
#include <vector>
#include <functional>
#include <type_traits>
#include "../config/config.h"
#include "delegate.hpp"
#include "fwd.hpp"

namespace entt {

/**
 * @brief Unmanaged signal handler declaration.
 *
 * Primary template isn't defined on purpose. All the specializations give a
 * compile-time error unless the template parameter is a function type.
 *
 * @tparam Function A valid function type.
 */
template<typename Function>
struct sigh;

/**
 * @brief Sink implementation.
 *
 * Primary template isn't defined on purpose. All the specializations give a
 * compile-time error unless the template parameter is a function type.
 *
 * @tparam Function A valid function type.
 */
template<typename Function>
class sink;

/**
 * @brief Sink implementation.
 *
 * A sink is an opaque object used to connect listeners to signals.

 * The function type for a listener is the one of the signal to which it
 * belongs.
 *
 * The clear separation between a signal and a sink permits to store the former
 * as private data member without exposing the publish functionality to the
 * users of a class.
 *
 * @tparam Ret Return type of a function type.
 * @tparam Args Types of arguments of a function type.
 */
template<typename Ret, typename... Args>
class sink<Ret(Args...)> {
    /*! @brief A signal is allowed to create sinks. */
    template<typename>
    friend struct sigh;

    sink(std::vector<delegate<Ret(Args...)>> *ref) ENTT_NOEXCEPT
        : calls{ref}
    {}

public:
    /**
     * @brief Returns false if at least a listener is connected to the sink.
     * @return True if the sink has no listeners connected, false otherwise.
     */
    bool empty() const ENTT_NOEXCEPT {
        return calls->empty();
    }

    /**
     * @brief Connects a free function to a signal.
     *
     * The signal handler performs checks to avoid multiple connections for free
     * functions.
     *
     * @tparam Function A valid free function pointer.
     */
    template<auto Function>
    void connect() {
        disconnect<Function>();
        delegate<Ret(Args...)> delegate{};
        delegate.template connect<Function>();
        calls->emplace_back(std::move(delegate));
    }

    /**
     * @brief Connects a member function or a free function with payload to a
     * signal.
     *
     * The signal isn't responsible for the connected object or the payload.
     * Users must always guarantee that the lifetime of the instance overcomes
     * the one  of the delegate. On the other side, the signal handler performs
     * checks to avoid multiple connections for the same function.

     * When used to connect a free function with payload, its signature must be
     * such that the instance is the first argument before the ones used to
     * define the delegate itself.
     *
     * @tparam Candidate Member or free function to connect to the signal.
     * @tparam Type Type of class or type of payload.
     * @param value_or_instance A valid pointer that fits the purpose.
     */
    template<auto Candidate, typename Type>
    void connect(Type *value_or_instance) {
        disconnect<Candidate>(value_or_instance);
        delegate<Ret(Args...)> delegate{};
        delegate.template connect<Candidate>(value_or_instance);
        calls->emplace_back(std::move(delegate));
    }

    /**
     * @brief Disconnects a free function from a signal.
     * @tparam Function A valid free function pointer.
     */
    template<auto Function>
    void disconnect() {
        delegate<Ret(Args...)> delegate{};
        delegate.template connect<Function>();
        calls->erase(std::remove(calls->begin(), calls->end(), std::move(delegate)), calls->end());
    }

    /**
     * @brief Disconnects a member function or a free function with payload from
     * a signal.
     * @tparam Candidate Member or free function to disconnect from the signal.
     * @tparam Type Type of class or type of payload.
     * @param value_or_instance A valid pointer that fits the purpose.
     */
    template<auto Candidate, typename Type>
    void disconnect(Type *value_or_instance) {
        delegate<Ret(Args...)> delegate{};
        delegate.template connect<Candidate>(value_or_instance);
        calls->erase(std::remove_if(calls->begin(), calls->end(), [delegate](const auto &other) {
            return other == delegate && other.instance() == delegate.instance();
        }), calls->end());
    }

    /**
     * @brief Disconnects member functions or free functions based on an
     * instance or specific payload.
     * @param value_or_instance A valid pointer that fits the purpose.
     */
    void disconnect(const void *value_or_instance) {
        calls->erase(std::remove_if(calls->begin(), calls->end(), [value_or_instance](const auto &delegate) {
            return value_or_instance == delegate.instance();
        }), calls->end());
    }

    /*! @brief Disconnects all the listeners from a signal. */
    void disconnect() {
        calls->clear();
    }

private:
    std::vector<delegate<Ret(Args...)>> *calls;
};

/**
 * @brief Unmanaged signal handler definition.
 *
 * Unmanaged signal handler. It works directly with naked pointers to classes
 * and pointers to member functions as well as pointers to free functions. Users
 * of this class are in charge of disconnecting instances before deleting them.
 *
 * This class serves mainly two purposes:
 *
 * * Creating signals to use later to notify a bunch of listeners.
 * * Collecting results from a set of functions like in a voting system.
 *
 * @tparam Ret Return type of a function type.
 * @tparam Args Types of arguments of a function type.
 */
template<typename Ret, typename... Args>
struct sigh<Ret(Args...)> {
    /*! @brief Unsigned integer type. */
    using size_type = typename std::vector<delegate<Ret(Args...)>>::size_type;
    /*! @brief Sink type. */
    using sink_type = entt::sink<Ret(Args...)>;

    /**
     * @brief Instance type when it comes to connecting member functions.
     * @tparam Class Type of class to which the member function belongs.
     */
    template<typename Class>
    using instance_type = Class *;

    /**
     * @brief Number of listeners connected to the signal.
     * @return Number of listeners currently connected.
     */
    size_type size() const ENTT_NOEXCEPT {
        return calls.size();
    }

    /**
     * @brief Returns false if at least a listener is connected to the signal.
     * @return True if the signal has no listeners connected, false otherwise.
     */
    bool empty() const ENTT_NOEXCEPT {
        return calls.empty();
    }

    /**
     * @brief Returns a sink object for the given signal.
     *
     * A sink is an opaque object used to connect listeners to signals.

     * The function type for a listener is the one of the signal to which it
     * belongs. The order of invocation of the listeners isn't guaranteed.
     *
     * @return A temporary sink object.
     */
    sink_type sink() ENTT_NOEXCEPT {
        return { &calls };
    }

    /**
     * @brief Triggers a signal.
     *
     * All the listeners are notified. Order isn't guaranteed.
     *
     * @param args Arguments to use to invoke listeners.
     */
    void publish(Args... args) const {
        for(auto pos = calls.size(); pos; --pos) {
            calls[pos-1](args...);
        }
    }

    /**
     * @brief Collects return values from the listeners.
     *
     * The collector must expose a call operator with the following properties:
     *
     * * The return type is either `void` or such that it's convertible to
     *   `bool`. In the second case, a true value will stop the iteration.
     * * The list of parameters is empty if `Ret` is `void`, otherwise it
     *   contains a single element such that `Ret` is convertible to it.
     *
     * @tparam Func Type of collector to use, if any.
     * @param func A valid function object.
     * @param args Arguments to use to invoke listeners.
     */
    template<typename Func>
    void collect(Func func, Args... args) const {
        bool stop = false;

        for(auto pos = calls.size(); pos && !stop; --pos) {
            if constexpr(std::is_void_v<Ret>) {
                if constexpr(std::is_invocable_r_v<bool, Func>) {
                    calls[pos-1](args...);
                    stop = func();
                } else {
                    calls[pos-1](args...);
                    func();
                }
            } else {
                if constexpr(std::is_invocable_r_v<bool, Func, Ret>) {
                    stop = func(calls[pos-1](args...));
                } else {
                    func(calls[pos-1](args...));
                }
            }
        }
    }

    /**
     * @brief Swaps listeners between the two signals.
     * @param lhs A valid signal object.
     * @param rhs A valid signal object.
     */
    friend void swap(sigh &lhs, sigh &rhs) {
        using std::swap;
        swap(lhs.calls, rhs.calls);
    }

private:
    std::vector<delegate<Ret(Args...)>> calls;
};

}

#endif // ENTT_SIGNAL_SIGH_HPP
<|endoftext|>


<commit_before>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"
#include "condor_debug.h"
static char *_FileName_ = __FILE__;

static struct hostent *host_ptr = NULL;
static char hostname[MAXHOSTNAMELEN];
static char full_hostname[MAXHOSTNAMELEN];
static unsigned int ip_addr;
static int hostnames_initialized = 0;
static void init_hostnames();

// Return our hostname in a static data buffer.
char *
my_hostname()
{
	if( ! hostnames_initialized ) {
		init_hostnames();
	}
	return hostname;
}

// Return our full hostname (with domain) in a static data buffer.
char*
my_full_hostname()
{
	if( ! hostnames_initialized ) {
		init_hostnames();
	}
	return full_hostname;
}

// Return the host-ordered, unsigned int version of our hostname.
unsigned int
my_ip_addr()
{
	if( ! hostnames_initialized ) {
		init_hostnames();
	}
	return ip_addr;
}

void
init_hostnames()
{
	char* tmp;

		// Get our local hostname, and strip off the domain if
		// gethostname returns it.
	if( gethostname(hostname, sizeof(hostname)) == 0 ) {
		tmp = strchr( hostname, '.' );
		if( tmp ) {
			*tmp = '\0';
		}
	} else {
		EXCEPT( "gethostname failed, errno = %d",
#ifndef WIN32
			errno );
#else
			WSAGetLastError() );
#endif
	}

		// Look up our official host information
	if( (host_ptr = gethostbyname(hostname)) == NULL ) {
		EXCEPT( "gethostbyname(%s) failed, errno = %d", hostname, errno );
	}

		// Grab our ip_addr and fully qualified hostname
	memcpy( &ip_addr, host_ptr->h_addr, (size_t)host_ptr->h_length );
	ip_addr = ntohl( ip_addr );

	strcpy( full_hostname, host_ptr->h_name );

	hostnames_initialized = TRUE;
}

<commit_msg>+ We now malloc the space we need instead of using fixed length   buffers. + We're much smarter about finding my_full_hostname, even in the face   of misconfigured machines.  If it's not where it should be, we   search through the host aliases, and even call res_init() to find   the default domain name that the resolver thinks it should use.   Ideally, we'd do an inverse query to DNS to be sure.<commit_after>/***************************Copyright-DO-NOT-REMOVE-THIS-LINE**
 * CONDOR Copyright Notice
 *
 * See LICENSE.TXT for additional notices and disclaimers.
 *
 * Copyright (c)1990-1998 CONDOR Team, Computer Sciences Department,
 * University of Wisconsin-Madison, Madison, WI.  All Rights Reserved.
 * No use of the CONDOR Software Program Source Code is authorized
 * without the express consent of the CONDOR Team.  For more information
 * contact: CONDOR Team, Attention: Professor Miron Livny,
 * 7367 Computer Sciences, 1210 W. Dayton St., Madison, WI 53706-1685,
 * (608) 262-0856 or miron@cs.wisc.edu.
 *
 * U.S. Government Rights Restrictions: Use, duplication, or disclosure
 * by the U.S. Government is subject to restrictions as set forth in
 * subparagraph (c)(1)(ii) of The Rights in Technical Data and Computer
 * Software clause at DFARS 252.227-7013 or subparagraphs (c)(1) and
 * (2) of Commercial Computer Software-Restricted Rights at 48 CFR
 * 52.227-19, as applicable, CONDOR Team, Attention: Professor Miron
 * Livny, 7367 Computer Sciences, 1210 W. Dayton St., Madison,
 * WI 53706-1685, (608) 262-0856 or miron@cs.wisc.edu.
****************************Copyright-DO-NOT-REMOVE-THIS-LINE**/

#include "condor_common.h"
#include "condor_debug.h"
static char *_FileName_ = __FILE__;

static struct hostent *host_ptr = NULL;
static char* hostname = NULL;
static char* full_hostname = NULL;
static unsigned int ip_addr;
static int hostnames_initialized = 0;
static void init_hostnames();

extern "C" {

// Return our hostname in a static data buffer.
char *
my_hostname()
{
	if( ! hostnames_initialized ) {
		init_hostnames();
	}
	return hostname;
}

// Return our full hostname (with domain) in a static data buffer.
char*
my_full_hostname()
{
	if( ! hostnames_initialized ) {
		init_hostnames();
	}
	return full_hostname;
}

// Return the host-ordered, unsigned int version of our hostname.
unsigned int
my_ip_addr()
{
	if( ! hostnames_initialized ) {
		init_hostnames();
	}
	return ip_addr;
}

} /* extern "C" */

#if !defined(WIN32)
#include <arpa/nameser.h>
#include <resolv.h>
#endif

void
init_hostnames()
{
	char *tmp, hostbuf[MAXHOSTNAMELEN];
	int i;

	if( hostname ) {
		free( hostname );
	}
	if( full_hostname ) {
		free( full_hostname );
		full_hostname = NULL;
	}

		// Get our local hostname, and strip off the domain if
		// gethostname returns it.
	if( gethostname(hostbuf, sizeof(hostbuf)) == 0 ) {
		if( (tmp = strchr(hostbuf, '.')) ) {
				// There's a '.' in the hostname, assume we've got the
				// full hostname here, save it, and trim the domain
				// off and save that as the hostname.
			full_hostname = strdup( hostbuf );
			*tmp = '\0';
		}
		hostname = strdup( hostbuf );
	} else {
		EXCEPT( "gethostname failed, errno = %d",
#ifndef WIN32
				errno );
#else
		WSAGetLastError() );
#endif
    }

		// Look up our official host information
	if( (host_ptr = gethostbyname(hostbuf)) == NULL ) {
		EXCEPT( "gethostbyname(%s) failed, errno = %d", hostbuf, errno );
	}

		// Grab our ip_addr
	memcpy( &ip_addr, host_ptr->h_addr, (size_t)host_ptr->h_length );
    ip_addr = ntohl( ip_addr );

	    // If we don't have our full_hostname yet, try to find it.
	if( ! full_hostname ) {
			// See if it's correct in the hostent we've got.
		if( (tmp = strchr(host_ptr->h_name, '.')) ) {
				// There's a '.' in the "name", use that as full.
			full_hostname = strdup( host_ptr->h_name );
		}
	}

	if( ! full_hostname ) {
			// We still haven't found it yet, try all the aliases
			// until we find one with a '.'
		for( i=0; host_ptr->h_aliases[i], !full_hostname; i++ ) {
			if( (tmp = strchr(host_ptr->h_aliases[i], '.')) ) {
				full_hostname = strdup( host_ptr->h_aliases[i] );
			}
		}
	}

#if !defined( WIN32 ) /* I'm not sure how to do this on NT */
	if( ! full_hostname ) {
			// We still haven't found it yet, try to use the
			// resolver.  *sigh*
		res_init();
		if( _res.defdname ) {
				// We know our default domain name, append that.
			strcat( hostbuf, "." );
			strcat( hostbuf, _res.defdname );
			full_hostname = strdup( hostbuf );
		}
	}
#endif /* WIN32 */
	if( ! full_hostname ) {
			// Still can't find it, just give up.
		full_hostname = strdup( hostname );
	}

	hostnames_initialized = TRUE;
}

<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/base/platform_thread.h"

#include "webrtc/base/atomicops.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/timeutils.h"
#include "webrtc/base/trace_event.h"

#if defined(WEBRTC_LINUX)
#include <sys/prctl.h>
#include <sys/syscall.h>
#endif

namespace rtc {

PlatformThreadId CurrentThreadId() {
  PlatformThreadId ret;
#if defined(WEBRTC_WIN)
  ret = GetCurrentThreadId();
#elif defined(WEBRTC_POSIX)
#if defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
  ret = pthread_mach_thread_np(pthread_self());
#elif defined(WEBRTC_LINUX)
  ret =  syscall(__NR_gettid);
#elif defined(WEBRTC_ANDROID)
  ret = gettid();
#else
  // Default implementation for nacl and solaris.
  ret = reinterpret_cast<pid_t>(pthread_self());
#endif
#endif  // defined(WEBRTC_POSIX)
  RTC_DCHECK(ret);
  return ret;
}

PlatformThreadRef CurrentThreadRef() {
#if defined(WEBRTC_WIN)
  return GetCurrentThreadId();
#elif defined(WEBRTC_POSIX)
  return pthread_self();
#endif
}

bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b) {
#if defined(WEBRTC_WIN)
  return a == b;
#elif defined(WEBRTC_POSIX)
  return pthread_equal(a, b);
#endif
}

void SetCurrentThreadName(const char* name) {
#if defined(WEBRTC_WIN)
  struct {
    DWORD dwType;
    LPCSTR szName;
    DWORD dwThreadID;
    DWORD dwFlags;
  } threadname_info = {0x1000, name, static_cast<DWORD>(-1), 0};

  __try {
    ::RaiseException(0x406D1388, 0, sizeof(threadname_info) / sizeof(DWORD),
                     reinterpret_cast<ULONG_PTR*>(&threadname_info));
  } __except (EXCEPTION_EXECUTE_HANDLER) {
  }
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
  prctl(PR_SET_NAME, reinterpret_cast<unsigned long>(name));
#elif defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
  pthread_setname_np(name);
#endif
}

namespace {
#if defined(WEBRTC_WIN)
void CALLBACK RaiseFlag(ULONG_PTR param) {
  *reinterpret_cast<bool*>(param) = true;
}
#else
struct ThreadAttributes {
  ThreadAttributes() { pthread_attr_init(&attr); }
  ~ThreadAttributes() { pthread_attr_destroy(&attr); }
  pthread_attr_t* operator&() { return &attr; }
  pthread_attr_t attr;
};
#endif  // defined(WEBRTC_WIN)
}

PlatformThread::PlatformThread(ThreadRunFunctionDeprecated func,
                               void* obj,
                               const char* thread_name)
    : run_function_deprecated_(func),
      obj_(obj),
      name_(thread_name ? thread_name : "webrtc") {
  RTC_DCHECK(func);
  RTC_DCHECK(name_.length() < 64);
  spawned_thread_checker_.DetachFromThread();
}

PlatformThread::PlatformThread(ThreadRunFunction func,
                               void* obj,
                               const char* thread_name,
                               ThreadPriority priority /*= kNormalPriority*/)
    : run_function_(func), priority_(priority), obj_(obj), name_(thread_name) {
  RTC_DCHECK(func);
  RTC_DCHECK(!name_.empty());
  // TODO(tommi): Consider lowering the limit to 15 (limit on Linux).
  RTC_DCHECK(name_.length() < 64);
  spawned_thread_checker_.DetachFromThread();
}

PlatformThread::~PlatformThread() {
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
#if defined(WEBRTC_WIN)
  RTC_DCHECK(!thread_);
  RTC_DCHECK(!thread_id_);
#endif  // defined(WEBRTC_WIN)
}

#if defined(WEBRTC_WIN)
DWORD WINAPI PlatformThread::StartThread(void* param) {
  // The GetLastError() function only returns valid results when it is called
  // after a Win32 API function that returns a "failed" result. A crash dump
  // contains the result from GetLastError() and to make sure it does not
  // falsely report a Windows error we call SetLastError here.
  ::SetLastError(ERROR_SUCCESS);
  static_cast<PlatformThread*>(param)->Run();
  return 0;
}
#else
void* PlatformThread::StartThread(void* param) {
  static_cast<PlatformThread*>(param)->Run();
  return 0;
}
#endif  // defined(WEBRTC_WIN)

void PlatformThread::Start() {
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
  RTC_DCHECK(!thread_) << "Thread already started?";
#if defined(WEBRTC_WIN)
  stop_ = false;

  // See bug 2902 for background on STACK_SIZE_PARAM_IS_A_RESERVATION.
  // Set the reserved stack stack size to 1M, which is the default on Windows
  // and Linux.
  thread_ = ::CreateThread(nullptr, 1024 * 1024, &StartThread, this,
                           STACK_SIZE_PARAM_IS_A_RESERVATION, &thread_id_);
  RTC_CHECK(thread_) << "CreateThread failed";
  RTC_DCHECK(thread_id_);
#else
  ThreadAttributes attr;
  // Set the stack stack size to 1M.
  pthread_attr_setstacksize(&attr, 1024 * 1024);
  RTC_CHECK_EQ(0, pthread_create(&thread_, &attr, &StartThread, this));
#endif  // defined(WEBRTC_WIN)
}

bool PlatformThread::IsRunning() const {
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
#if defined(WEBRTC_WIN)
  return thread_ != nullptr;
#else
  return thread_ != 0;
#endif  // defined(WEBRTC_WIN)
}

PlatformThreadRef PlatformThread::GetThreadRef() const {
#if defined(WEBRTC_WIN)
  return thread_id_;
#else
  return thread_;
#endif  // defined(WEBRTC_WIN)
}

void PlatformThread::Stop() {
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
  if (!IsRunning())
    return;

#if defined(WEBRTC_WIN)
  // Set stop_ to |true| on the worker thread.
  bool queued = QueueAPC(&RaiseFlag, reinterpret_cast<ULONG_PTR>(&stop_));
  // Queuing the APC can fail if the thread is being terminated.
  RTC_CHECK(queued || GetLastError() == ERROR_GEN_FAILURE);
  WaitForSingleObject(thread_, INFINITE);
  CloseHandle(thread_);
  thread_ = nullptr;
  thread_id_ = 0;
#else
  if (!run_function_)
    RTC_CHECK_EQ(1, AtomicOps::Increment(&stop_flag_));
  RTC_CHECK_EQ(0, pthread_join(thread_, nullptr));
  if (!run_function_)
    AtomicOps::ReleaseStore(&stop_flag_, 0);
  thread_ = 0;
#endif  // defined(WEBRTC_WIN)
  spawned_thread_checker_.DetachFromThread();
}

// TODO(tommi): Deprecate the loop behavior in PlatformThread.
// * Introduce a new callback type that returns void.
// * Remove potential for a busy loop in PlatformThread.
// * Delegate the responsibility for how to stop the thread, to the
//   implementation that actually uses the thread.
// All implementations will need to be aware of how the thread should be stopped
// and encouraging a busy polling loop, can be costly in terms of power and cpu.
void PlatformThread::Run() {
  // Attach the worker thread checker to this thread.
  RTC_DCHECK(spawned_thread_checker_.CalledOnValidThread());
  rtc::SetCurrentThreadName(name_.c_str());

  if (run_function_) {
    SetPriority(priority_);
    run_function_(obj_);
    return;
  }

// TODO(tommi): Delete the rest of this function when looping isn't supported.
#if RTC_DCHECK_IS_ON
  // These constants control the busy loop detection algorithm below.
  // |kMaxLoopCount| controls the limit for how many times we allow the loop
  // to run within a period, before DCHECKing.
  // |kPeriodToMeasureMs| controls how long that period is.
  static const int kMaxLoopCount = 1000;
  static const int kPeriodToMeasureMs = 100;
  int64_t loop_stamps[kMaxLoopCount] = {};
  int64_t sequence_nr = 0;
#endif

  do {
    TRACE_EVENT1("webrtc", "PlatformThread::Run", "name", name_.c_str());

    // The interface contract of Start/Stop is that for a successful call to
    // Start, there should be at least one call to the run function.  So we
    // call the function before checking |stop_|.
    if (!run_function_deprecated_(obj_))
      break;
#if RTC_DCHECK_IS_ON
    auto id = sequence_nr % kMaxLoopCount;
    loop_stamps[id] = rtc::TimeMillis();
    if (sequence_nr > kMaxLoopCount) {
      auto compare_id = (id + 1) % kMaxLoopCount;
      auto diff = loop_stamps[id] - loop_stamps[compare_id];
      RTC_DCHECK_GE(diff, 0);
      if (diff < kPeriodToMeasureMs) {
        RTC_NOTREACHED() << "This thread is too busy: " << name_ << " " << diff
                         << "ms sequence=" << sequence_nr << " "
                         << loop_stamps[id] << " vs " << loop_stamps[compare_id]
                         << ", " << id << " vs " << compare_id;
      }
    }
    ++sequence_nr;
#endif
#if defined(WEBRTC_WIN)
    // Alertable sleep to permit RaiseFlag to run and update |stop_|.
    SleepEx(0, true);
  } while (!stop_);
#else
#if defined(WEBRTC_MAC)
    sched_yield();
#else
    static const struct timespec ts_null = {0};
    nanosleep(&ts_null, nullptr);
#endif
  } while (!AtomicOps::AcquireLoad(&stop_flag_));
#endif  // defined(WEBRTC_WIN)
}

bool PlatformThread::SetPriority(ThreadPriority priority) {
#if RTC_DCHECK_IS_ON
  if (run_function_) {
    // The non-deprecated way of how this function gets called, is that it must
    // be called on the worker thread itself.
    RTC_DCHECK(spawned_thread_checker_.CalledOnValidThread());
  } else {
    // In the case of deprecated use of this method, it must be called on the
    // same thread as the PlatformThread object is constructed on.
    RTC_DCHECK(thread_checker_.CalledOnValidThread());
    RTC_DCHECK(IsRunning());
  }
#endif

#if defined(WEBRTC_WIN)
  return SetThreadPriority(thread_, priority) != FALSE;
#elif defined(__native_client__)
  // Setting thread priorities is not supported in NaCl.
  return true;
#elif defined(WEBRTC_CHROMIUM_BUILD) && defined(WEBRTC_LINUX)
  // TODO(tommi): Switch to the same mechanism as Chromium uses for changing
  // thread priorities.
  return true;
#else
#ifdef WEBRTC_THREAD_RR
  const int policy = SCHED_RR;
#else
  const int policy = SCHED_FIFO;
#endif
  const int min_prio = sched_get_priority_min(policy);
  const int max_prio = sched_get_priority_max(policy);
  if (min_prio == -1 || max_prio == -1) {
    return false;
  }

  if (max_prio - min_prio <= 2)
    return false;

  // Convert webrtc priority to system priorities:
  sched_param param;
  const int top_prio = max_prio - 1;
  const int low_prio = min_prio + 1;
  switch (priority) {
    case kLowPriority:
      param.sched_priority = low_prio;
      break;
    case kNormalPriority:
      // The -1 ensures that the kHighPriority is always greater or equal to
      // kNormalPriority.
      param.sched_priority = (low_prio + top_prio - 1) / 2;
      break;
    case kHighPriority:
      param.sched_priority = std::max(top_prio - 2, low_prio);
      break;
    case kHighestPriority:
      param.sched_priority = std::max(top_prio - 1, low_prio);
      break;
    case kRealtimePriority:
      param.sched_priority = top_prio;
      break;
  }
  return pthread_setschedparam(thread_, policy, &param) == 0;
#endif  // defined(WEBRTC_WIN)
}

#if defined(WEBRTC_WIN)
bool PlatformThread::QueueAPC(PAPCFUNC function, ULONG_PTR data) {
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
  RTC_DCHECK(IsRunning());

  return QueueUserAPC(function, thread_, data) != FALSE;
}
#endif

}  // namespace rtc
<commit_msg>Add a missing DCHECK to PlatformThread::SetPriority. This DCHECK is for the 'new and improved' way of setting thread priority. What could happen is that code that's migrating over to the new method might still have a lingering SetPriority call, that could incorrectly bind the 'spawned_thread_checker_' to the construction thread.<commit_after>/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/base/platform_thread.h"

#include "webrtc/base/atomicops.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/timeutils.h"
#include "webrtc/base/trace_event.h"

#if defined(WEBRTC_LINUX)
#include <sys/prctl.h>
#include <sys/syscall.h>
#endif

namespace rtc {

PlatformThreadId CurrentThreadId() {
  PlatformThreadId ret;
#if defined(WEBRTC_WIN)
  ret = GetCurrentThreadId();
#elif defined(WEBRTC_POSIX)
#if defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
  ret = pthread_mach_thread_np(pthread_self());
#elif defined(WEBRTC_LINUX)
  ret =  syscall(__NR_gettid);
#elif defined(WEBRTC_ANDROID)
  ret = gettid();
#else
  // Default implementation for nacl and solaris.
  ret = reinterpret_cast<pid_t>(pthread_self());
#endif
#endif  // defined(WEBRTC_POSIX)
  RTC_DCHECK(ret);
  return ret;
}

PlatformThreadRef CurrentThreadRef() {
#if defined(WEBRTC_WIN)
  return GetCurrentThreadId();
#elif defined(WEBRTC_POSIX)
  return pthread_self();
#endif
}

bool IsThreadRefEqual(const PlatformThreadRef& a, const PlatformThreadRef& b) {
#if defined(WEBRTC_WIN)
  return a == b;
#elif defined(WEBRTC_POSIX)
  return pthread_equal(a, b);
#endif
}

void SetCurrentThreadName(const char* name) {
#if defined(WEBRTC_WIN)
  struct {
    DWORD dwType;
    LPCSTR szName;
    DWORD dwThreadID;
    DWORD dwFlags;
  } threadname_info = {0x1000, name, static_cast<DWORD>(-1), 0};

  __try {
    ::RaiseException(0x406D1388, 0, sizeof(threadname_info) / sizeof(DWORD),
                     reinterpret_cast<ULONG_PTR*>(&threadname_info));
  } __except (EXCEPTION_EXECUTE_HANDLER) {
  }
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_ANDROID)
  prctl(PR_SET_NAME, reinterpret_cast<unsigned long>(name));
#elif defined(WEBRTC_MAC) || defined(WEBRTC_IOS)
  pthread_setname_np(name);
#endif
}

namespace {
#if defined(WEBRTC_WIN)
void CALLBACK RaiseFlag(ULONG_PTR param) {
  *reinterpret_cast<bool*>(param) = true;
}
#else
struct ThreadAttributes {
  ThreadAttributes() { pthread_attr_init(&attr); }
  ~ThreadAttributes() { pthread_attr_destroy(&attr); }
  pthread_attr_t* operator&() { return &attr; }
  pthread_attr_t attr;
};
#endif  // defined(WEBRTC_WIN)
}

PlatformThread::PlatformThread(ThreadRunFunctionDeprecated func,
                               void* obj,
                               const char* thread_name)
    : run_function_deprecated_(func),
      obj_(obj),
      name_(thread_name ? thread_name : "webrtc") {
  RTC_DCHECK(func);
  RTC_DCHECK(name_.length() < 64);
  spawned_thread_checker_.DetachFromThread();
}

PlatformThread::PlatformThread(ThreadRunFunction func,
                               void* obj,
                               const char* thread_name,
                               ThreadPriority priority /*= kNormalPriority*/)
    : run_function_(func), priority_(priority), obj_(obj), name_(thread_name) {
  RTC_DCHECK(func);
  RTC_DCHECK(!name_.empty());
  // TODO(tommi): Consider lowering the limit to 15 (limit on Linux).
  RTC_DCHECK(name_.length() < 64);
  spawned_thread_checker_.DetachFromThread();
}

PlatformThread::~PlatformThread() {
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
#if defined(WEBRTC_WIN)
  RTC_DCHECK(!thread_);
  RTC_DCHECK(!thread_id_);
#endif  // defined(WEBRTC_WIN)
}

#if defined(WEBRTC_WIN)
DWORD WINAPI PlatformThread::StartThread(void* param) {
  // The GetLastError() function only returns valid results when it is called
  // after a Win32 API function that returns a "failed" result. A crash dump
  // contains the result from GetLastError() and to make sure it does not
  // falsely report a Windows error we call SetLastError here.
  ::SetLastError(ERROR_SUCCESS);
  static_cast<PlatformThread*>(param)->Run();
  return 0;
}
#else
void* PlatformThread::StartThread(void* param) {
  static_cast<PlatformThread*>(param)->Run();
  return 0;
}
#endif  // defined(WEBRTC_WIN)

void PlatformThread::Start() {
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
  RTC_DCHECK(!thread_) << "Thread already started?";
#if defined(WEBRTC_WIN)
  stop_ = false;

  // See bug 2902 for background on STACK_SIZE_PARAM_IS_A_RESERVATION.
  // Set the reserved stack stack size to 1M, which is the default on Windows
  // and Linux.
  thread_ = ::CreateThread(nullptr, 1024 * 1024, &StartThread, this,
                           STACK_SIZE_PARAM_IS_A_RESERVATION, &thread_id_);
  RTC_CHECK(thread_) << "CreateThread failed";
  RTC_DCHECK(thread_id_);
#else
  ThreadAttributes attr;
  // Set the stack stack size to 1M.
  pthread_attr_setstacksize(&attr, 1024 * 1024);
  RTC_CHECK_EQ(0, pthread_create(&thread_, &attr, &StartThread, this));
#endif  // defined(WEBRTC_WIN)
}

bool PlatformThread::IsRunning() const {
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
#if defined(WEBRTC_WIN)
  return thread_ != nullptr;
#else
  return thread_ != 0;
#endif  // defined(WEBRTC_WIN)
}

PlatformThreadRef PlatformThread::GetThreadRef() const {
#if defined(WEBRTC_WIN)
  return thread_id_;
#else
  return thread_;
#endif  // defined(WEBRTC_WIN)
}

void PlatformThread::Stop() {
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
  if (!IsRunning())
    return;

#if defined(WEBRTC_WIN)
  // Set stop_ to |true| on the worker thread.
  bool queued = QueueAPC(&RaiseFlag, reinterpret_cast<ULONG_PTR>(&stop_));
  // Queuing the APC can fail if the thread is being terminated.
  RTC_CHECK(queued || GetLastError() == ERROR_GEN_FAILURE);
  WaitForSingleObject(thread_, INFINITE);
  CloseHandle(thread_);
  thread_ = nullptr;
  thread_id_ = 0;
#else
  if (!run_function_)
    RTC_CHECK_EQ(1, AtomicOps::Increment(&stop_flag_));
  RTC_CHECK_EQ(0, pthread_join(thread_, nullptr));
  if (!run_function_)
    AtomicOps::ReleaseStore(&stop_flag_, 0);
  thread_ = 0;
#endif  // defined(WEBRTC_WIN)
  spawned_thread_checker_.DetachFromThread();
}

// TODO(tommi): Deprecate the loop behavior in PlatformThread.
// * Introduce a new callback type that returns void.
// * Remove potential for a busy loop in PlatformThread.
// * Delegate the responsibility for how to stop the thread, to the
//   implementation that actually uses the thread.
// All implementations will need to be aware of how the thread should be stopped
// and encouraging a busy polling loop, can be costly in terms of power and cpu.
void PlatformThread::Run() {
  // Attach the worker thread checker to this thread.
  RTC_DCHECK(spawned_thread_checker_.CalledOnValidThread());
  rtc::SetCurrentThreadName(name_.c_str());

  if (run_function_) {
    SetPriority(priority_);
    run_function_(obj_);
    return;
  }

// TODO(tommi): Delete the rest of this function when looping isn't supported.
#if RTC_DCHECK_IS_ON
  // These constants control the busy loop detection algorithm below.
  // |kMaxLoopCount| controls the limit for how many times we allow the loop
  // to run within a period, before DCHECKing.
  // |kPeriodToMeasureMs| controls how long that period is.
  static const int kMaxLoopCount = 1000;
  static const int kPeriodToMeasureMs = 100;
  int64_t loop_stamps[kMaxLoopCount] = {};
  int64_t sequence_nr = 0;
#endif

  do {
    TRACE_EVENT1("webrtc", "PlatformThread::Run", "name", name_.c_str());

    // The interface contract of Start/Stop is that for a successful call to
    // Start, there should be at least one call to the run function.  So we
    // call the function before checking |stop_|.
    if (!run_function_deprecated_(obj_))
      break;
#if RTC_DCHECK_IS_ON
    auto id = sequence_nr % kMaxLoopCount;
    loop_stamps[id] = rtc::TimeMillis();
    if (sequence_nr > kMaxLoopCount) {
      auto compare_id = (id + 1) % kMaxLoopCount;
      auto diff = loop_stamps[id] - loop_stamps[compare_id];
      RTC_DCHECK_GE(diff, 0);
      if (diff < kPeriodToMeasureMs) {
        RTC_NOTREACHED() << "This thread is too busy: " << name_ << " " << diff
                         << "ms sequence=" << sequence_nr << " "
                         << loop_stamps[id] << " vs " << loop_stamps[compare_id]
                         << ", " << id << " vs " << compare_id;
      }
    }
    ++sequence_nr;
#endif
#if defined(WEBRTC_WIN)
    // Alertable sleep to permit RaiseFlag to run and update |stop_|.
    SleepEx(0, true);
  } while (!stop_);
#else
#if defined(WEBRTC_MAC)
    sched_yield();
#else
    static const struct timespec ts_null = {0};
    nanosleep(&ts_null, nullptr);
#endif
  } while (!AtomicOps::AcquireLoad(&stop_flag_));
#endif  // defined(WEBRTC_WIN)
}

bool PlatformThread::SetPriority(ThreadPriority priority) {
#if RTC_DCHECK_IS_ON
  if (run_function_) {
    // The non-deprecated way of how this function gets called, is that it must
    // be called on the worker thread itself.
    RTC_DCHECK(!thread_checker_.CalledOnValidThread());
    RTC_DCHECK(spawned_thread_checker_.CalledOnValidThread());
  } else {
    // In the case of deprecated use of this method, it must be called on the
    // same thread as the PlatformThread object is constructed on.
    RTC_DCHECK(thread_checker_.CalledOnValidThread());
    RTC_DCHECK(IsRunning());
  }
#endif

#if defined(WEBRTC_WIN)
  return SetThreadPriority(thread_, priority) != FALSE;
#elif defined(__native_client__)
  // Setting thread priorities is not supported in NaCl.
  return true;
#elif defined(WEBRTC_CHROMIUM_BUILD) && defined(WEBRTC_LINUX)
  // TODO(tommi): Switch to the same mechanism as Chromium uses for changing
  // thread priorities.
  return true;
#else
#ifdef WEBRTC_THREAD_RR
  const int policy = SCHED_RR;
#else
  const int policy = SCHED_FIFO;
#endif
  const int min_prio = sched_get_priority_min(policy);
  const int max_prio = sched_get_priority_max(policy);
  if (min_prio == -1 || max_prio == -1) {
    return false;
  }

  if (max_prio - min_prio <= 2)
    return false;

  // Convert webrtc priority to system priorities:
  sched_param param;
  const int top_prio = max_prio - 1;
  const int low_prio = min_prio + 1;
  switch (priority) {
    case kLowPriority:
      param.sched_priority = low_prio;
      break;
    case kNormalPriority:
      // The -1 ensures that the kHighPriority is always greater or equal to
      // kNormalPriority.
      param.sched_priority = (low_prio + top_prio - 1) / 2;
      break;
    case kHighPriority:
      param.sched_priority = std::max(top_prio - 2, low_prio);
      break;
    case kHighestPriority:
      param.sched_priority = std::max(top_prio - 1, low_prio);
      break;
    case kRealtimePriority:
      param.sched_priority = top_prio;
      break;
  }
  return pthread_setschedparam(thread_, policy, &param) == 0;
#endif  // defined(WEBRTC_WIN)
}

#if defined(WEBRTC_WIN)
bool PlatformThread::QueueAPC(PAPCFUNC function, ULONG_PTR data) {
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
  RTC_DCHECK(IsRunning());

  return QueueUserAPC(function, thread_, data) != FALSE;
}
#endif

}  // namespace rtc
<|endoftext|>


<commit_before>/*
 * MRustC - Rust Compiler
 * - By John Hodge (Mutabah/thePowersGang)
 *
 * synexts/lang_item.cpp
 * - Binds language items to #[lang_item] tagged items
 */
#include <synext.hpp>
#include "../common.hpp"
#include "../ast/ast.hpp"
#include "../ast/crate.hpp"

void handle_lang_item(const Span& sp, AST::Crate& crate, const AST::Path& path, const ::std::string& name, AST::eItemType type)
{
    if(name == "phantom_fn") {
        // - Just save path
    }
    else if( name == "send" ) {
        // Don't care, Send is fully library in mrustc
        // - Needed for `static`
    }
    else if( name == "sync" ) {
        // Don't care, Sync is fully library in mrustc
        // - Needed for `static`
    }
    else if( name == "sized" ) {
        DEBUG("Bind 'sized' to " << path);
    }
    else if( name == "copy" ) {
        DEBUG("Bind 'copy' to " << path);
    }
    // ops traits
    else if( name == "drop" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "add" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "sub" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "mul" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "div" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "rem" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "neg" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "not" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "bitand" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitor"  ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitxor" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "shl" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "shr" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "add_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "sub_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "div_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "rem_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "mul_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitand_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitor_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitxor_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "shl_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "shr_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "index" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "deref" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "index_mut" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "deref_mut" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "fn"      ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "fn_mut"  ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "fn_once" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "eq"  ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "ord" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "unsize" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "coerce_unsized" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "iterator" ) { /* mrustc just desugars? */ }

    else if( name == "debug_trait" ) { /* TODO: Poke derive() with this */ }

    // Structs
    else if( name == "non_zero" ) { }
    else if( name == "phantom_data" ) { }
    else if( name == "range_full" ) { }
    else if( name == "range" ) { }
    else if( name == "range_from" ) { }
    else if( name == "range_to" ) { }
    else if( name == "unsafe_cell" ) { }

    // Functions
    else if( name == "panic" ) { }
    else if( name == "panic_bounds_check" ) { }
    else if( name == "panic_fmt" ) { }
    else if( name == "str_eq" ) { }
    // - builtin `box` support
    else if( name == "exchange_malloc" ) { }
    else if( name == "exchange_free" ) { }
    else if( name == "box_free" ) { }
    else if( name == "owned_box" ) { }

    else {
        ERROR(sp, E0000, "Unknown language item '" << name << "'");
    }

    auto rv = crate.m_lang_items.insert( ::std::make_pair( name, ::AST::Path(path) ) );
    if( !rv.second ) {
        ERROR(sp, E0000, "Duplicate definition of language item '" << name << "'");
    }
}

class Decorator_LangItem:
    public ExpandDecorator
{
public:
    AttrStage stage() const override { return AttrStage::EarlyPost; }
    void handle(const Span& sp, const AST::MetaItem& attr, AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item& i) const override
    {
        TU_MATCH_DEF(::AST::Item, (i), (e),
        (
            TODO(sp, "Unknown item type with #[lang=\""<<attr<<"\"] attached at " << path);
            ),
        (Function,
            handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_FN);
            ),
        (Struct,
            handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_STRUCT);
            ),
        (Trait,
            handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_TRAIT);
            )
        )
    }

    void handle(const Span& sp, const AST::MetaItem& mi, AST::Crate& crate, const AST::Module& mod, AST::ImplDef& impl) const override {
        const ::std::string& name = mi.string();

             if( name == "i8" ) {}
        else if( name == "u8" ) {}
        else if( name == "i16" ) {}
        else if( name == "u16" ) {}
        else if( name == "i32" ) {}
        else if( name == "u32" ) {}
        else if( name == "i64" ) {}
        else if( name == "u64" ) {}
        else if( name == "isize" ) {}
        else if( name == "usize" ) {}
        else if( name == "const_ptr" ) {}
        else if( name == "mut_ptr" ) {}
        // rustc_unicode
        else if( name == "char" ) {}
        // collections
        else if( name == "str" ) {}
        else if( name == "slice" ) {}
        // std - interestingly
        else if( name == "f32" ) {}
        else if( name == "f64" ) {}
        else {
            ERROR(sp, E0000, "Unknown lang item '" << name << "' on impl");
        }

        // TODO: Somehow annotate these impls to allow them to provide inherents?
        // - mrustc is lazy and inefficient, so these don't matter :)
    }
};

STATIC_DECORATOR("lang", Decorator_LangItem)

<commit_msg>Expand lang - "start"<commit_after>/*
 * MRustC - Rust Compiler
 * - By John Hodge (Mutabah/thePowersGang)
 *
 * synexts/lang_item.cpp
 * - Binds language items to #[lang_item] tagged items
 */
#include <synext.hpp>
#include "../common.hpp"
#include "../ast/ast.hpp"
#include "../ast/crate.hpp"

void handle_lang_item(const Span& sp, AST::Crate& crate, const AST::Path& path, const ::std::string& name, AST::eItemType type)
{
    if(name == "phantom_fn") {
        // - Just save path
    }
    else if( name == "send" ) {
        // Don't care, Send is fully library in mrustc
        // - Needed for `static`
    }
    else if( name == "sync" ) {
        // Don't care, Sync is fully library in mrustc
        // - Needed for `static`
    }
    else if( name == "sized" ) {
        DEBUG("Bind 'sized' to " << path);
    }
    else if( name == "copy" ) {
        DEBUG("Bind 'copy' to " << path);
    }
    // ops traits
    else if( name == "drop" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "add" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "sub" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "mul" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "div" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "rem" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "neg" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "not" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "bitand" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitor"  ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitxor" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "shl" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "shr" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "add_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "sub_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "div_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "rem_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "mul_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitand_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitor_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "bitxor_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "shl_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "shr_assign" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "index" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "deref" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "index_mut" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "deref_mut" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "fn"      ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "fn_mut"  ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "fn_once" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "eq"  ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "ord" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "unsize" ) { DEBUG("Bind '"<<name<<"' to " << path); }
    else if( name == "coerce_unsized" ) { DEBUG("Bind '"<<name<<"' to " << path); }

    else if( name == "iterator" ) { /* mrustc just desugars? */ }

    else if( name == "debug_trait" ) { /* TODO: Poke derive() with this */ }

    // Structs
    else if( name == "non_zero" ) { }
    else if( name == "phantom_data" ) { }
    else if( name == "range_full" ) { }
    else if( name == "range" ) { }
    else if( name == "range_from" ) { }
    else if( name == "range_to" ) { }
    else if( name == "unsafe_cell" ) { }

    // Functions
    else if( name == "panic" ) { }
    else if( name == "panic_bounds_check" ) { }
    else if( name == "panic_fmt" ) { }
    else if( name == "str_eq" ) { }
    // - builtin `box` support
    else if( name == "exchange_malloc" ) { }
    else if( name == "exchange_free" ) { }
    else if( name == "box_free" ) { }
    else if( name == "owned_box" ) { }
    // - start
    else if( name == "start" ) { }

    else {
        ERROR(sp, E0000, "Unknown language item '" << name << "'");
    }

    auto rv = crate.m_lang_items.insert( ::std::make_pair( name, ::AST::Path(path) ) );
    if( !rv.second ) {
        ERROR(sp, E0000, "Duplicate definition of language item '" << name << "' - " << rv.first->second << " and " << path);
    }
}

class Decorator_LangItem:
    public ExpandDecorator
{
public:
    AttrStage stage() const override { return AttrStage::EarlyPost; }
    void handle(const Span& sp, const AST::MetaItem& attr, AST::Crate& crate, const AST::Path& path, AST::Module& mod, AST::Item& i) const override
    {
        TU_MATCH_DEF(::AST::Item, (i), (e),
        (
            TODO(sp, "Unknown item type with #[lang=\""<<attr<<"\"] attached at " << path);
            ),
        (Function,
            handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_FN);
            ),
        (Struct,
            handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_STRUCT);
            ),
        (Trait,
            handle_lang_item(sp, crate, path, attr.string(), AST::ITEM_TRAIT);
            )
        )
    }

    void handle(const Span& sp, const AST::MetaItem& mi, AST::Crate& crate, const AST::Module& mod, AST::ImplDef& impl) const override {
        const ::std::string& name = mi.string();

             if( name == "i8" ) {}
        else if( name == "u8" ) {}
        else if( name == "i16" ) {}
        else if( name == "u16" ) {}
        else if( name == "i32" ) {}
        else if( name == "u32" ) {}
        else if( name == "i64" ) {}
        else if( name == "u64" ) {}
        else if( name == "isize" ) {}
        else if( name == "usize" ) {}
        else if( name == "const_ptr" ) {}
        else if( name == "mut_ptr" ) {}
        // rustc_unicode
        else if( name == "char" ) {}
        // collections
        else if( name == "str" ) {}
        else if( name == "slice" ) {}
        // std - interestingly
        else if( name == "f32" ) {}
        else if( name == "f64" ) {}
        else {
            ERROR(sp, E0000, "Unknown lang item '" << name << "' on impl");
        }

        // TODO: Somehow annotate these impls to allow them to provide inherents?
        // - mrustc is lazy and inefficient, so these don't matter :)
    }
};

STATIC_DECORATOR("lang", Decorator_LangItem)

<|endoftext|>


<commit_before>#include "Sketch.h"

#include "chr/gl/draw/Sphere.h"

using namespace std;
using namespace chr;
using namespace gl;
using namespace draw;
using namespace path;

constexpr float R1 = 6;
constexpr float R2 = 300;
constexpr float TURNS = 20;
constexpr float DD1 = 1.0f;
constexpr float DD2 = 3.0f;

constexpr int NUM_SPHERES = 1000;
constexpr float SWELL_FACTOR = 0.125f;

Sketch::Sketch()
    :
    shader(InputSource::resource("Shader.vert"), InputSource::resource("Shader.frag"))
{}

void Sketch::setup()
{
    texture = Texture::ImageRequest("checker.png")
        .setFlags(image::FLAGS_RBGA)
        .setFilters(GL_NEAREST, GL_NEAREST);

    batch
        .setShader(shader)
        .setShaderColor(0.25f, 1.0f, 0.0f, 1)
        .setTexture(texture);

    Sphere()
        .setFrontFace(CW)
        .setSectorCount(20)
        .setStackCount(10)
        .setRadius(5)
        .append(batch, Matrix());

    instanceBuffer = InstanceBuffer(GL_DYNAMIC_DRAW);

    spiral.setup(surface, R1, R2, TURNS, DD1, DD2, 10 * NUM_SPHERES, 10);

    // ---

    glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glDepthMask(GL_TRUE);

    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

void Sketch::resize()
{
    camera
        .setFov(45)
        .setClip(0.1f, 1000.0f)
        .setWindowSize(windowInfo.size);
}

void Sketch::update()
{
    spiral.update(surface, clock()->getTime(), SWELL_FACTOR);
}

void Sketch::draw()
{
    glClearColor(0.4f, 0.8f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    // ---

    camera.getViewMatrix()
        .setIdentity()
        .translate(0, 0, -300)
        .rotateX(115 * D2R)
        .rotateY(0);

    State()
        .setShaderMatrix<VIEW>(camera.getViewMatrix())
        .setShaderMatrix<PROJECTION>(camera.getProjectionMatrix())
        .setShaderUniform("u_light_position", camera.getEyePosition())
        .setShaderUniform("u_light_color", glm::vec3(1.0, 1.0, 1.0))
        .setShaderUniform("u_light_intensity", 1.0f)
        .setShaderUniform("u_ambient_color", glm::vec3(0, 0, 0))
        .setShaderUniform("u_specular_color", glm::vec3(1, 1, 1))
        .setShaderUniform("u_shininess", 25.0f)
        .setShaderUniform("u_has_texture", true)
        .setShaderUniform("u_has_color", true) // i.e. do not use diffuse color but vertex color instead
        .apply();

    threadSpiral(instanceBuffer, spiral.path, 10);
    batch.flush(instanceBuffer);

    State()
        .setShaderMatrix<MVP>(camera.getViewProjectionMatrix())
        .apply();
}

void Sketch::threadSpiral(InstanceBuffer &instanceBuffer, const FollowablePath3D &path, float spacing)
{
    instanceBuffer.clearMatrices();

    float offset = 0;
    Matrix matrix;

    for (int i = 0; i < NUM_SPHERES; i++)
    {
        auto value = path.offsetToValue(offset);
        value.applyToMatrix(matrix);
        instanceBuffer.addMatrix(matrix);
        offset += spacing;
    }
}
<commit_msg>TestingDynamicInstancing: Re-indenting<commit_after>#include "Sketch.h"

#include "chr/gl/draw/Sphere.h"

using namespace std;
using namespace chr;
using namespace gl;
using namespace draw;
using namespace path;

constexpr float R1 = 6;
constexpr float R2 = 300;
constexpr float TURNS = 20;
constexpr float DD1 = 1.0f;
constexpr float DD2 = 3.0f;

constexpr int NUM_SPHERES = 1000;
constexpr float SWELL_FACTOR = 0.125f;

Sketch::Sketch()
:
shader(InputSource::resource("Shader.vert"), InputSource::resource("Shader.frag"))
{}

void Sketch::setup()
{
  texture = Texture::ImageRequest("checker.png")
    .setFlags(image::FLAGS_RBGA)
    .setFilters(GL_NEAREST, GL_NEAREST);

  batch
    .setShader(shader)
    .setShaderColor(0.25f, 1.0f, 0.0f, 1)
    .setTexture(texture);

  Sphere()
    .setFrontFace(CW)
    .setSectorCount(20)
    .setStackCount(10)
    .setRadius(5)
    .append(batch, Matrix());

  instanceBuffer = InstanceBuffer(GL_DYNAMIC_DRAW);

  spiral.setup(surface, R1, R2, TURNS, DD1, DD2, 10 * NUM_SPHERES, 10);

  // ---

  glEnable(GL_CULL_FACE);
  glEnable(GL_DEPTH_TEST);
  glDepthMask(GL_TRUE);

  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}

void Sketch::resize()
{
  camera
    .setFov(45)
    .setClip(0.1f, 1000.0f)
    .setWindowSize(windowInfo.size);
}

void Sketch::update()
{
  spiral.update(surface, clock()->getTime(), SWELL_FACTOR);
}

void Sketch::draw()
{
  glClearColor(0.4f, 0.8f, 1.0f, 1.0f);
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

  // ---

  camera.getViewMatrix()
    .setIdentity()
    .translate(0, 0, -300)
    .rotateX(115 * D2R)
    .rotateY(0);

  State()
    .setShaderMatrix<VIEW>(camera.getViewMatrix())
    .setShaderMatrix<PROJECTION>(camera.getProjectionMatrix())
    .setShaderUniform("u_light_position", camera.getEyePosition())
    .setShaderUniform("u_light_color", glm::vec3(1.0, 1.0, 1.0))
    .setShaderUniform("u_light_intensity", 1.0f)
    .setShaderUniform("u_ambient_color", glm::vec3(0, 0, 0))
    .setShaderUniform("u_specular_color", glm::vec3(1, 1, 1))
    .setShaderUniform("u_shininess", 25.0f)
    .setShaderUniform("u_has_texture", true)
    .setShaderUniform("u_has_color", true) // i.e. do not use diffuse color but vertex color instead
    .apply();

  threadSpiral(instanceBuffer, spiral.path, 10);
  batch.flush(instanceBuffer);

  State()
    .setShaderMatrix<MVP>(camera.getViewProjectionMatrix())
    .apply();
}

void Sketch::threadSpiral(InstanceBuffer &instanceBuffer, const FollowablePath3D &path, float spacing)
{
  instanceBuffer.clearMatrices();

  float offset = 0;
  Matrix matrix;

  for (int i = 0; i < NUM_SPHERES; i++)
  {
    auto value = path.offsetToValue(offset);
    value.applyToMatrix(matrix);
    instanceBuffer.addMatrix(matrix);
    offset += spacing;
  }
}
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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 <iostream>

#include "itkIntensityWindowingImageFilter.h"
#include "itkRandomImageSource.h"

int itkIntensityWindowingImageFilterTest(int, char* [] )
{
  std::cout << "itkIntensityWindowingImageFilterTest Start" << std::endl;

  typedef itk::Image<float,3> TestInputImage;
  typedef itk::Image<float,3> TestOutputImage;

  TestInputImage::RegionType region;
  TestInputImage::SizeType   size; size.Fill(64);
  TestInputImage::IndexType  index; index.Fill(0);

  region.SetIndex (index);
  region.SetSize (size);

  typedef itk::IntensityWindowingImageFilter<TestInputImage,TestOutputImage> FilterType;
  FilterType::Pointer filter = FilterType::New();

  // Now generate a real image

  typedef itk::RandomImageSource<TestInputImage> SourceType;
  SourceType::Pointer source = SourceType::New();
  TestInputImage::SizeValueType randomSize[3] = {17, 8, 20};

  // Set up source
  source->SetSize(randomSize);
  double minValue = -128.0;
  double maxValue = 127.0;

  source->SetMin( static_cast< TestInputImage::PixelType >( minValue ) );
  source->SetMax( static_cast< TestInputImage::PixelType >( maxValue ) );

  filter->SetInput(source->GetOutput());

  const double desiredMinimum = -1.0;
  const double desiredMaximum =  1.0;

  const float  windowMinimum = -50.0f;
  const float  windowMaximum =  50.0f;

  filter->SetOutputMinimum( desiredMinimum );
  filter->SetOutputMaximum( desiredMaximum );
  filter->SetWindowMinimum( windowMinimum  );
  filter->SetWindowMaximum( windowMaximum  );

  std::cout << "Window minimum:maximum = " << windowMinimum << ":" << windowMaximum << ", equivalent window:level = " << filter->GetWindow() << ":" << filter->GetLevel() << std::endl;

  try
    {
    filter->UpdateLargestPossibleRegion();
    filter->SetFunctor(filter->GetFunctor());
    }
  catch (itk::ExceptionObject& e)
    {
    std::cerr << "Exception detected: "  << e;
    return -1;
    }

  typedef itk::MinimumMaximumImageCalculator< TestOutputImage > CalculatorType;
  CalculatorType::Pointer calculator  =  CalculatorType::New();

  calculator->SetImage( filter->GetOutput() );

  calculator->Compute();

  const double tolerance = 1e-7;

  const double obtainedMinimum = calculator->GetMinimum();
  const double obtainedMaximum = calculator->GetMaximum();

  if( itk::Math::abs( obtainedMinimum - desiredMinimum ) > tolerance )
    {
    std::cerr << "Error in minimum" << std::endl;
    std::cerr << "Expected minimum = " << desiredMinimum  << std::endl;
    std::cerr << "Obtained minimum = " << obtainedMinimum << std::endl;
    return EXIT_FAILURE;
    }

  if( itk::Math::abs( obtainedMaximum - desiredMaximum ) > tolerance )
    {
    std::cerr << "Error in maximum" << std::endl;
    std::cerr << "Expected maximum = " << desiredMaximum  << std::endl;
    std::cerr << "Obtained maximum = " << obtainedMaximum << std::endl;
    return EXIT_FAILURE;
    }

  const float  window = 50.0f;
  const float  level =  50.0f;

  filter->SetWindowLevel( window, level  );

  std::cout << "Window:level = "
            << filter->GetWindow() << ":"
            << filter->GetLevel()
            << ", equivalent window minimum:maximum = "
            << filter->GetWindowMinimum()
            << ":" << filter->GetWindowMaximum() << std::endl;

  try
    {
    filter->UpdateLargestPossibleRegion();
    }
  catch (itk::ExceptionObject& e)
    {
    std::cerr << "Exception detected: "  << e;
    return -1;
    }

  calculator->Compute();

  const double obtainedMinimum2 = calculator->GetMinimum();
  const double obtainedMaximum2 = calculator->GetMaximum();

  if( itk::Math::abs( obtainedMinimum2 - desiredMinimum ) > tolerance )
    {
    std::cerr << "Error in minimum" << std::endl;
    std::cerr << "Expected minimum = " << desiredMinimum  << std::endl;
    std::cerr << "Obtained minimum = " << obtainedMinimum2 << std::endl;
    return EXIT_FAILURE;
    }

  if( itk::Math::abs( obtainedMaximum2 - desiredMaximum ) > tolerance )
    {
    std::cerr << "Error in maximum" << std::endl;
    std::cerr << "Expected maximum = " << desiredMaximum  << std::endl;
    std::cerr << "Obtained maximum = " << obtainedMaximum2 << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "Test PASSED ! " << std::endl;
  return EXIT_SUCCESS;

}
<commit_msg>STYLE: Improve the itkIntensityWindowingImageFilter test style<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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 <iostream>

#include "itkIntensityWindowingImageFilter.h"
#include "itkRandomImageSource.h"

int itkIntensityWindowingImageFilterTest(int, char* [] )
{
  std::cout << "Testing itk::IntensityWindowingImageFilter class" << std::endl;

  const unsigned int Dimension = 3;
  typedef float PixelType;

  typedef itk::Image< PixelType, Dimension > TestInputImage;
  typedef itk::Image< PixelType, Dimension > TestOutputImage;

  TestInputImage::RegionType region;
  TestInputImage::SizeType   size; size.Fill(64);
  TestInputImage::IndexType  index; index.Fill(0);

  region.SetIndex (index);
  region.SetSize (size);

  typedef itk::IntensityWindowingImageFilter< TestInputImage, TestOutputImage > FilterType;
  FilterType::Pointer filter = FilterType::New();

  // Now generate a real image

  typedef itk::RandomImageSource<TestInputImage> SourceType;
  SourceType::Pointer source = SourceType::New();
  TestInputImage::SizeValueType randomSize[3] = {17, 8, 20};

  // Set up source
  source->SetSize(randomSize);
  double minValue = -128.0;
  double maxValue =  127.0;

  source->SetMin( static_cast< TestInputImage::PixelType >( minValue ) );
  source->SetMax( static_cast< TestInputImage::PixelType >( maxValue ) );

  filter->SetInput(source->GetOutput());

  const double desiredMinimum = -1.0;
  const double desiredMaximum =  1.0;

  const float  windowMinimum = -50.0f;
  const float  windowMaximum =  50.0f;

  filter->SetOutputMinimum( desiredMinimum );
  filter->SetOutputMaximum( desiredMaximum );
  filter->SetWindowMinimum( windowMinimum  );
  filter->SetWindowMaximum( windowMaximum  );

  std::cout << "Window minimum:maximum = "
    << windowMinimum << ":" << windowMaximum
    << ", equivalent window:level = "
    << filter->GetWindow() << ":" << filter->GetLevel() << std::endl;

  try
    {
    filter->UpdateLargestPossibleRegion();
    filter->SetFunctor(filter->GetFunctor());
    }
  catch (itk::ExceptionObject& e)
    {
    std::cerr << "Exception detected: " << e;
    return -1;
    }

  typedef itk::MinimumMaximumImageCalculator< TestOutputImage > CalculatorType;
  CalculatorType::Pointer calculator = CalculatorType::New();

  calculator->SetImage( filter->GetOutput() );

  calculator->Compute();

  const double tolerance = 1e-7;

  const double obtainedMinimum = calculator->GetMinimum();
  const double obtainedMaximum = calculator->GetMaximum();

  if( itk::Math::abs( obtainedMinimum - desiredMinimum ) > tolerance )
    {
    std::cerr << "Error in minimum" << std::endl;
    std::cerr << "Expected minimum = " << desiredMinimum  << std::endl;
    std::cerr << "Obtained minimum = " << obtainedMinimum << std::endl;
    return EXIT_FAILURE;
    }

  if( itk::Math::abs( obtainedMaximum - desiredMaximum ) > tolerance )
    {
    std::cerr << "Error in maximum" << std::endl;
    std::cerr << "Expected maximum = " << desiredMaximum  << std::endl;
    std::cerr << "Obtained maximum = " << obtainedMaximum << std::endl;
    return EXIT_FAILURE;
    }

  const float window = 50.0f;
  const float level  = 50.0f;

  filter->SetWindowLevel( window, level );

  std::cout << "Window:level = "
            << filter->GetWindow() << ":"
            << filter->GetLevel()
            << ", equivalent window minimum:maximum = "
            << filter->GetWindowMinimum()
            << ":" << filter->GetWindowMaximum() << std::endl;

  try
    {
    filter->UpdateLargestPossibleRegion();
    }
  catch (itk::ExceptionObject& e)
    {
    std::cerr << "Exception detected: " << e;
    return -1;
    }

  calculator->Compute();

  const double obtainedMinimum2 = calculator->GetMinimum();
  const double obtainedMaximum2 = calculator->GetMaximum();

  if( itk::Math::abs( obtainedMinimum2 - desiredMinimum ) > tolerance )
    {
    std::cerr << "Error in minimum" << std::endl;
    std::cerr << "Expected minimum = " << desiredMinimum   << std::endl;
    std::cerr << "Obtained minimum = " << obtainedMinimum2 << std::endl;
    return EXIT_FAILURE;
    }

  if( itk::Math::abs( obtainedMaximum2 - desiredMaximum ) > tolerance )
    {
    std::cerr << "Error in maximum" << std::endl;
    std::cerr << "Expected maximum = " << desiredMaximum   << std::endl;
    std::cerr << "Obtained maximum = " << obtainedMaximum2 << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "Test PASSED ! " << std::endl;
  return EXIT_SUCCESS;

}
<|endoftext|>


<commit_before>#pragma once

#include <cstdlib>

#include <vector>
#include <stdexcept>
#include <functional>

#include "math/vector3.hpp"

//#include "projection.hpp"
//#include "integrator.hpp"

// this needs to be improved to be able to have different precisions
// and perhaps different color systems (if applicable)
struct color
{
	float r, g, b, a;
};

// A screen raster, which holds a pixel buffer
struct Raster
{
	Raster(size_t width, size_t height)
	  : m_width(width), m_height(height)
	{
		m_data.resize(m_width * m_height);
	}

	const color *operator[](size_t y) const
		{ return &m_data[y * m_width]; }
	color *operator[](size_t y)
		{ return &m_data[y * m_width]; }

	size_t width() const { return m_width; }
	size_t height() const { return m_height; }

private:
	std::vector<color> m_data;
	const size_t m_width, m_height;
};

template <typename RasterTy, typename IntegratorTy>
void render(RasterTy &raster, IntegratorTy &&integrator)
{
	// this is where the rendering happens:
	// 1. project a camera ray for every pixel
	// (according to some subpixel sampling distribution)
	// 2. integrate the camera ray to assign a color
	// 3. post-process as needed
	// 4. output the rest

	// this is just a test render
	for (size_t y = 0; y < raster.height(); ++y) {
		for (size_t x = 0; x < raster.width(); ++x) {
		    float px = ((float)x / raster.width() - 0.5f) * 2;
		    float py = ((float)y / raster.height() - 0.5f) * 2;

		    math::float3 cam_dir = normalize(math::float3(px, py, 0.5f));
		    math::float3 cam_pos(0, 0, 0);

		    math::float3 color = integrator(cam_pos, cam_dir);

		    raster[y][x].r = color.x;
		    raster[y][x].g = color.y;
		    raster[y][x].b = color.z;
		}
	}
}
<commit_msg>Resize can be replaced with constructor, more elegant.<commit_after>#pragma once

#include <cstdlib>

#include <vector>
#include <stdexcept>
#include <functional>

#include "math/vector3.hpp"

//#include "projection.hpp"
//#include "integrator.hpp"

// this needs to be improved to be able to have different precisions
// and perhaps different color systems (if applicable)
struct color
{
	float r, g, b, a;
};

// A screen raster, which holds a pixel buffer
struct Raster
{
	Raster(size_t width, size_t height)
	  : m_width(width), m_height(height), m_data(width * height)
	{
	}

	const color *operator[](size_t y) const
		{ return &m_data[y * m_width]; }
	color *operator[](size_t y)
		{ return &m_data[y * m_width]; }

	size_t width() const { return m_width; }
	size_t height() const { return m_height; }

private:
	const size_t m_width, m_height;
	std::vector<color> m_data;
};

template <typename RasterTy, typename IntegratorTy>
void render(RasterTy &raster, IntegratorTy &&integrator)
{
	// this is where the rendering happens:
	// 1. project a camera ray for every pixel
	// (according to some subpixel sampling distribution)
	// 2. integrate the camera ray to assign a color
	// 3. post-process as needed
	// 4. output the rest

	// this is just a test render
	for (size_t y = 0; y < raster.height(); ++y) {
		for (size_t x = 0; x < raster.width(); ++x) {
		    float px = ((float)x / raster.width() - 0.5f) * 2;
		    float py = ((float)y / raster.height() - 0.5f) * 2;

		    math::float3 cam_dir = normalize(math::float3(px, py, 0.5f));
		    math::float3 cam_pos(0, 0, 0);

		    math::float3 color = integrator(cam_pos, cam_dir);

		    raster[y][x].r = color.x;
		    raster[y][x].g = color.y;
		    raster[y][x].b = color.z;
		}
	}
}
<|endoftext|>