<commit_before>/*
 * Copyright (C) 2013-2016 Alexander Saprykin <xelfium@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#ifndef PLIBSYS_TESTS_STATIC
#  define BOOST_TEST_DYN_LINK
#endif

#define BOOST_TEST_MODULE puthread_test

#include "plibsys.h"

#ifdef PLIBSYS_TESTS_STATIC
#  include <boost/test/included/unit_test.hpp>
#else
#  include <boost/test/unit_test.hpp>
#endif

static pint thread_wakes_1 = 0;
static pint thread_wakes_2 = 0;
static pint thread_to_wakes = 100;
static volatile pboolean is_threads_working = TRUE;

static P_HANDLE thread1_id = (P_HANDLE) NULL;
static P_HANDLE thread2_id = (P_HANDLE) NULL;
static PUThread *thread1_obj = NULL;
static PUThread *thread2_obj = NULL;

static PUThreadKey *tls_key = NULL;
static volatile pint free_counter = 0;

extern "C" ppointer pmem_alloc (psize nbytes)
{
	P_UNUSED (nbytes);
	return (ppointer) NULL;
}

extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
{
	P_UNUSED (block);
	P_UNUSED (nbytes);
	return (ppointer) NULL;
}

extern "C" void pmem_free (ppointer block)
{
	P_UNUSED (block);
}

static void free_with_check (ppointer mem)
{
	p_free (mem);
	p_atomic_int_inc (&free_counter);
}

static void * test_thread_func (void *data)
{
	pint *counter =  static_cast < pint * > (data);

	if ((*counter) == 1) {
		thread1_id  = p_uthread_current_id ();
		thread1_obj = p_uthread_current ();
	} else {
		thread2_id  = p_uthread_current_id ();
		thread2_obj = p_uthread_current ();
	}

	p_uthread_set_local (tls_key, (ppointer) p_uthread_current_id ());

	*counter = 0;

	while (is_threads_working == TRUE) {
		p_uthread_sleep (10);
		++(*counter);
		p_uthread_yield ();

		if (p_uthread_get_local (tls_key) != (ppointer) p_uthread_current_id ())
			p_uthread_exit (-1);
	}

	p_uthread_exit (*counter);

	return NULL;
}

static void * test_thread_nonjoinable_func (void *data)
{
	pint *counter =  static_cast < pint * > (data);

	is_threads_working = TRUE;

	for (int i = thread_to_wakes; i > 0; --i) {
		p_uthread_sleep (10);
		++(*counter);
		p_uthread_yield ();
	}

	is_threads_working = FALSE;

	p_uthread_exit (0);

	return NULL;
}

static void * test_thread_tls_func (void *data)
{
	pint self_thread_free = *((pint *) data);

	pint *tls_value = (pint *) p_malloc0 (sizeof (pint));
	*tls_value = 0;
	p_uthread_set_local (tls_key, (ppointer) tls_value);

	pint prev_tls = 0;
	pint counter  = 0;

	while (is_threads_working == TRUE) {
		p_uthread_sleep (10);

		pint *last_tls = (pint *) p_uthread_get_local (tls_key);

		if ((*last_tls) != prev_tls)
			p_uthread_exit (-1);

		pint *tls_new_value = (pint *) p_malloc0 (sizeof (pint));

		*tls_new_value = (*last_tls) + 1;
		prev_tls       = (*last_tls) + 1;

		p_uthread_replace_local (tls_key, (ppointer) tls_new_value);

		if (self_thread_free)
			p_free (last_tls);

		++counter;

		p_uthread_yield ();
	}

	if (self_thread_free) {
		pint *last_tls = (pint *) p_uthread_get_local (tls_key);

		if ((*last_tls) != prev_tls)
			p_uthread_exit (-1);

		p_free (last_tls);

		p_uthread_replace_local (tls_key, (ppointer) NULL);
	}

	p_uthread_exit (counter);

	return NULL;
}

BOOST_AUTO_TEST_SUITE (BOOST_TEST_MODULE)

BOOST_AUTO_TEST_CASE (puthread_nomem_test)
{
	p_libsys_init ();

	PUThreadKey *thread_key = p_uthread_local_new (p_free);
	BOOST_CHECK (thread_key != NULL);

	PMemVTable vtable;

	vtable.free	= pmem_free;
	vtable.malloc	= pmem_alloc;
	vtable.realloc	= pmem_realloc;

	BOOST_CHECK (p_mem_set_vtable (&vtable) == TRUE);

	BOOST_CHECK (p_uthread_create ((PUThreadFunc) test_thread_func,
				       (ppointer) &thread_wakes_1,
				       TRUE) == NULL);

	BOOST_CHECK (p_uthread_create_full ((PUThreadFunc) test_thread_func,
					    (ppointer) &thread_wakes_2,
					    TRUE,
					    P_UTHREAD_PRIORITY_NORMAL,
					    0) == NULL);

	BOOST_CHECK (p_uthread_current () == NULL);
	BOOST_CHECK (p_uthread_local_new (NULL) == NULL);

	p_uthread_set_local (thread_key, PINT_TO_POINTER (10));
	BOOST_CHECK (p_uthread_get_local (thread_key) == NULL);
	p_uthread_replace_local (thread_key, PINT_TO_POINTER (10));
	BOOST_CHECK (p_uthread_get_local (thread_key) == NULL);

	p_mem_restore_vtable ();

	p_uthread_local_free (thread_key);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_bad_input_test)
{
	p_libsys_init ();

	BOOST_CHECK (p_uthread_create (NULL, NULL, false) == NULL);
	BOOST_CHECK (p_uthread_create_full (NULL, NULL, false, P_UTHREAD_PRIORITY_NORMAL, 0) == NULL);
	BOOST_CHECK (p_uthread_join (NULL) == -1);
	BOOST_CHECK (p_uthread_set_priority (NULL, P_UTHREAD_PRIORITY_NORMAL) == FALSE);
	BOOST_CHECK (p_uthread_get_local (NULL) == NULL);
	p_uthread_set_local (NULL, NULL);
	p_uthread_replace_local (NULL, NULL);
	p_uthread_ref (NULL);
	p_uthread_unref (NULL);
	p_uthread_local_free (NULL);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_general_test)
{
	p_libsys_init ();

	thread_wakes_1 = 1;
	thread_wakes_2 = 2;

	tls_key = p_uthread_local_new (NULL);
	BOOST_CHECK (tls_key != NULL);

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_func,
					   (ppointer) &thread_wakes_1,
					   TRUE);

	PUThread *thr2 = p_uthread_create_full ((PUThreadFunc) test_thread_func,
						(ppointer) &thread_wakes_2,
						TRUE,
						P_UTHREAD_PRIORITY_NORMAL,
						0);

	p_uthread_ref (thr1);

	BOOST_CHECK (p_uthread_set_priority (thr1, P_UTHREAD_PRIORITY_NORMAL) == TRUE);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	BOOST_CHECK (p_uthread_join (thr1) == thread_wakes_1);
	BOOST_CHECK (p_uthread_join (thr2) == thread_wakes_2);

	BOOST_REQUIRE (thread1_id != thread2_id);
	BOOST_CHECK (thread1_id != p_uthread_current_id () &&
		     thread2_id != p_uthread_current_id ());

	BOOST_CHECK (thread1_obj == thr1);
	BOOST_CHECK (thread2_obj == thr2);

	p_uthread_local_free (tls_key);
	p_uthread_unref (thr1);
	p_uthread_unref (thr2);

	p_uthread_unref (thr1);

	PUThread *cur_thr = p_uthread_current ();
	BOOST_CHECK (cur_thr != NULL);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_nonjoinable_test)
{
	p_libsys_init ();

	thread_wakes_1 = 0;

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_nonjoinable_func,
					   (ppointer) &thread_wakes_1,
					   FALSE);

	BOOST_REQUIRE (thr1 != NULL);

	p_uthread_sleep (3000);

	BOOST_CHECK (p_uthread_join (thr1) == -1);

	while (is_threads_working == TRUE)
		p_uthread_sleep (10);

	BOOST_CHECK (thread_wakes_1 == thread_to_wakes);

	p_uthread_unref (thr1);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_tls_test)
{
	p_libsys_init ();

	/* With destroy notification */
	tls_key = p_uthread_local_new (free_with_check);

	is_threads_working = TRUE;

	pint self_thread_free = 0;

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
					   (ppointer) &self_thread_free,
					   TRUE);

	PUThread *thr2 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
					   (ppointer) &self_thread_free,
					   TRUE);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	pint total_counter = 0;

	total_counter += (p_uthread_join (thr1) + 1);
	total_counter += (p_uthread_join (thr2) + 1);

	BOOST_CHECK (total_counter == free_counter);

	p_uthread_local_free (tls_key);
	p_uthread_unref (thr1);
	p_uthread_unref (thr2);

	/* Without destroy notification */
	tls_key = p_uthread_local_new (NULL);

	free_counter       = 0;
	is_threads_working = TRUE;
	self_thread_free   = 1;

	thr1 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
				 (ppointer) &self_thread_free,
				 TRUE);

	thr2 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
				 (ppointer) &self_thread_free,
				 TRUE);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	total_counter = 0;

	total_counter += (p_uthread_join (thr1) + 1);
	total_counter += (p_uthread_join (thr2) + 1);

	BOOST_CHECK (total_counter > 0);
	BOOST_CHECK (free_counter == 0);

	p_uthread_local_free (tls_key);
	p_uthread_unref (thr1);
	p_uthread_unref (thr2);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>tests: Add check for custom thread stack size<commit_after>/*
 * Copyright (C) 2013-2016 Alexander Saprykin <xelfium@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

#ifndef PLIBSYS_TESTS_STATIC
#  define BOOST_TEST_DYN_LINK
#endif

#define BOOST_TEST_MODULE puthread_test

#include "plibsys.h"

#ifdef PLIBSYS_TESTS_STATIC
#  include <boost/test/included/unit_test.hpp>
#else
#  include <boost/test/unit_test.hpp>
#endif

static pint thread_wakes_1 = 0;
static pint thread_wakes_2 = 0;
static pint thread_to_wakes = 100;
static volatile pboolean is_threads_working = TRUE;

static P_HANDLE thread1_id = (P_HANDLE) NULL;
static P_HANDLE thread2_id = (P_HANDLE) NULL;
static PUThread *thread1_obj = NULL;
static PUThread *thread2_obj = NULL;

static PUThreadKey *tls_key = NULL;
static volatile pint free_counter = 0;

extern "C" ppointer pmem_alloc (psize nbytes)
{
	P_UNUSED (nbytes);
	return (ppointer) NULL;
}

extern "C" ppointer pmem_realloc (ppointer block, psize nbytes)
{
	P_UNUSED (block);
	P_UNUSED (nbytes);
	return (ppointer) NULL;
}

extern "C" void pmem_free (ppointer block)
{
	P_UNUSED (block);
}

static void free_with_check (ppointer mem)
{
	p_free (mem);
	p_atomic_int_inc (&free_counter);
}

static void * test_thread_func (void *data)
{
	pint *counter =  static_cast < pint * > (data);

	if ((*counter) == 1) {
		thread1_id  = p_uthread_current_id ();
		thread1_obj = p_uthread_current ();
	} else {
		thread2_id  = p_uthread_current_id ();
		thread2_obj = p_uthread_current ();
	}

	p_uthread_set_local (tls_key, (ppointer) p_uthread_current_id ());

	*counter = 0;

	while (is_threads_working == TRUE) {
		p_uthread_sleep (10);
		++(*counter);
		p_uthread_yield ();

		if (p_uthread_get_local (tls_key) != (ppointer) p_uthread_current_id ())
			p_uthread_exit (-1);
	}

	p_uthread_exit (*counter);

	return NULL;
}

static void * test_thread_nonjoinable_func (void *data)
{
	pint *counter =  static_cast < pint * > (data);

	is_threads_working = TRUE;

	for (int i = thread_to_wakes; i > 0; --i) {
		p_uthread_sleep (10);
		++(*counter);
		p_uthread_yield ();
	}

	is_threads_working = FALSE;

	p_uthread_exit (0);

	return NULL;
}

static void * test_thread_tls_func (void *data)
{
	pint self_thread_free = *((pint *) data);

	pint *tls_value = (pint *) p_malloc0 (sizeof (pint));
	*tls_value = 0;
	p_uthread_set_local (tls_key, (ppointer) tls_value);

	pint prev_tls = 0;
	pint counter  = 0;

	while (is_threads_working == TRUE) {
		p_uthread_sleep (10);

		pint *last_tls = (pint *) p_uthread_get_local (tls_key);

		if ((*last_tls) != prev_tls)
			p_uthread_exit (-1);

		pint *tls_new_value = (pint *) p_malloc0 (sizeof (pint));

		*tls_new_value = (*last_tls) + 1;
		prev_tls       = (*last_tls) + 1;

		p_uthread_replace_local (tls_key, (ppointer) tls_new_value);

		if (self_thread_free)
			p_free (last_tls);

		++counter;

		p_uthread_yield ();
	}

	if (self_thread_free) {
		pint *last_tls = (pint *) p_uthread_get_local (tls_key);

		if ((*last_tls) != prev_tls)
			p_uthread_exit (-1);

		p_free (last_tls);

		p_uthread_replace_local (tls_key, (ppointer) NULL);
	}

	p_uthread_exit (counter);

	return NULL;
}

BOOST_AUTO_TEST_SUITE (BOOST_TEST_MODULE)

BOOST_AUTO_TEST_CASE (puthread_nomem_test)
{
	p_libsys_init ();

	PUThreadKey *thread_key = p_uthread_local_new (p_free);
	BOOST_CHECK (thread_key != NULL);

	PMemVTable vtable;

	vtable.free	= pmem_free;
	vtable.malloc	= pmem_alloc;
	vtable.realloc	= pmem_realloc;

	BOOST_CHECK (p_mem_set_vtable (&vtable) == TRUE);

	BOOST_CHECK (p_uthread_create ((PUThreadFunc) test_thread_func,
				       (ppointer) &thread_wakes_1,
				       TRUE) == NULL);

	BOOST_CHECK (p_uthread_create_full ((PUThreadFunc) test_thread_func,
					    (ppointer) &thread_wakes_2,
					    TRUE,
					    P_UTHREAD_PRIORITY_NORMAL,
					    0) == NULL);

	BOOST_CHECK (p_uthread_current () == NULL);
	BOOST_CHECK (p_uthread_local_new (NULL) == NULL);

	p_uthread_set_local (thread_key, PINT_TO_POINTER (10));
	BOOST_CHECK (p_uthread_get_local (thread_key) == NULL);
	p_uthread_replace_local (thread_key, PINT_TO_POINTER (10));
	BOOST_CHECK (p_uthread_get_local (thread_key) == NULL);

	p_mem_restore_vtable ();

	p_uthread_local_free (thread_key);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_bad_input_test)
{
	p_libsys_init ();

	BOOST_CHECK (p_uthread_create (NULL, NULL, false) == NULL);
	BOOST_CHECK (p_uthread_create_full (NULL, NULL, false, P_UTHREAD_PRIORITY_NORMAL, 0) == NULL);
	BOOST_CHECK (p_uthread_join (NULL) == -1);
	BOOST_CHECK (p_uthread_set_priority (NULL, P_UTHREAD_PRIORITY_NORMAL) == FALSE);
	BOOST_CHECK (p_uthread_get_local (NULL) == NULL);
	p_uthread_set_local (NULL, NULL);
	p_uthread_replace_local (NULL, NULL);
	p_uthread_ref (NULL);
	p_uthread_unref (NULL);
	p_uthread_local_free (NULL);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_general_test)
{
	p_libsys_init ();

	thread_wakes_1 = 1;
	thread_wakes_2 = 2;

	tls_key = p_uthread_local_new (NULL);
	BOOST_CHECK (tls_key != NULL);

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_func,
					   (ppointer) &thread_wakes_1,
					   TRUE);

	PUThread *thr2 = p_uthread_create_full ((PUThreadFunc) test_thread_func,
						(ppointer) &thread_wakes_2,
						TRUE,
						P_UTHREAD_PRIORITY_NORMAL,
						64 * 1024);

	p_uthread_ref (thr1);

	BOOST_CHECK (p_uthread_set_priority (thr1, P_UTHREAD_PRIORITY_NORMAL) == TRUE);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	BOOST_CHECK (p_uthread_join (thr1) == thread_wakes_1);
	BOOST_CHECK (p_uthread_join (thr2) == thread_wakes_2);

	BOOST_REQUIRE (thread1_id != thread2_id);
	BOOST_CHECK (thread1_id != p_uthread_current_id () &&
		     thread2_id != p_uthread_current_id ());

	BOOST_CHECK (thread1_obj == thr1);
	BOOST_CHECK (thread2_obj == thr2);

	p_uthread_local_free (tls_key);
	p_uthread_unref (thr1);
	p_uthread_unref (thr2);

	p_uthread_unref (thr1);

	PUThread *cur_thr = p_uthread_current ();
	BOOST_CHECK (cur_thr != NULL);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_nonjoinable_test)
{
	p_libsys_init ();

	thread_wakes_1 = 0;

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_nonjoinable_func,
					   (ppointer) &thread_wakes_1,
					   FALSE);

	BOOST_REQUIRE (thr1 != NULL);

	p_uthread_sleep (3000);

	BOOST_CHECK (p_uthread_join (thr1) == -1);

	while (is_threads_working == TRUE)
		p_uthread_sleep (10);

	BOOST_CHECK (thread_wakes_1 == thread_to_wakes);

	p_uthread_unref (thr1);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_CASE (puthread_tls_test)
{
	p_libsys_init ();

	/* With destroy notification */
	tls_key = p_uthread_local_new (free_with_check);

	is_threads_working = TRUE;

	pint self_thread_free = 0;

	PUThread *thr1 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
					   (ppointer) &self_thread_free,
					   TRUE);

	PUThread *thr2 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
					   (ppointer) &self_thread_free,
					   TRUE);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	pint total_counter = 0;

	total_counter += (p_uthread_join (thr1) + 1);
	total_counter += (p_uthread_join (thr2) + 1);

	BOOST_CHECK (total_counter == free_counter);

	p_uthread_local_free (tls_key);
	p_uthread_unref (thr1);
	p_uthread_unref (thr2);

	/* Without destroy notification */
	tls_key = p_uthread_local_new (NULL);

	free_counter       = 0;
	is_threads_working = TRUE;
	self_thread_free   = 1;

	thr1 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
				 (ppointer) &self_thread_free,
				 TRUE);

	thr2 = p_uthread_create ((PUThreadFunc) test_thread_tls_func,
				 (ppointer) &self_thread_free,
				 TRUE);

	BOOST_REQUIRE (thr1 != NULL);
	BOOST_REQUIRE (thr2 != NULL);

	p_uthread_sleep (5000);

	is_threads_working = FALSE;

	total_counter = 0;

	total_counter += (p_uthread_join (thr1) + 1);
	total_counter += (p_uthread_join (thr2) + 1);

	BOOST_CHECK (total_counter > 0);
	BOOST_CHECK (free_counter == 0);

	p_uthread_local_free (tls_key);
	p_uthread_unref (thr1);
	p_uthread_unref (thr2);

	p_libsys_shutdown ();
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before><commit_msg>fdo#78799 - ignore overlayed monitors with co-incident origin.<commit_after><|endoftext|>


<commit_before>// window.cpp
#include "window.h"

#include <stdio.h>

#ifdef _MSC_VER
#include <stddef.h>
#if (_MSC_VER < 1900)
#define snprintf sprintf_s
#endif
#endif

#include <stdint.h>

#if _WIN32
#include <Windows.h>
#include <Windowsx.h>
#else
#error "The slang-graphics library currently only supports Windows platforms"
#endif

namespace gfx {

#if _WIN32

struct OSString
{
    OSString(char const* begin, char const* end)
    {
        _initialize(begin, end - begin);
    }

    OSString(char const* begin)
    {
        _initialize(begin, strlen(begin));
    }

    ~OSString()
    {
        free(mBegin);
    }

    operator WCHAR const*()
    {
        return mBegin;
    }

private:
    WCHAR* mBegin;
    WCHAR* mEnd;

    void _initialize(char const* input, size_t inputSize)
    {
        const DWORD dwFlags = 0;
        int outputCodeUnitCount = ::MultiByteToWideChar(CP_UTF8, dwFlags, input, int(inputSize), nullptr, 0);

        WCHAR* buffer = (WCHAR*)malloc(sizeof(WCHAR) * (outputCodeUnitCount + 1));

        ::MultiByteToWideChar(CP_UTF8, dwFlags, input, int(inputSize), buffer, outputCodeUnitCount);
        buffer[outputCodeUnitCount] = 0;

        mBegin = buffer;
        mEnd = buffer + outputCodeUnitCount;
    }
};

struct ApplicationContext
{
    HINSTANCE instance;
    int showCommand = SW_SHOWDEFAULT;
    int resultCode = 0;
};

static uint64_t gTimerFrequency;

static void initApplication(ApplicationContext* context)
{
    LARGE_INTEGER timerFrequency;
    QueryPerformanceFrequency(&timerFrequency);
    gTimerFrequency = timerFrequency.QuadPart;
}

/// Run an application given the specified callback and command-line arguments.
int runApplication(
    ApplicationFunc     func,
    int                 argc,
    char const* const*  argv)
{
    ApplicationContext context;
    context.instance = (HINSTANCE) GetModuleHandle(0);
    initApplication(&context);
    func(&context);
    return context.resultCode;
}

int runWindowsApplication(
    ApplicationFunc     func,
    void*               instance,
    int                 showCommand)
{
    ApplicationContext context;
    context.instance = (HINSTANCE) instance;
    context.showCommand = showCommand;
    initApplication(&context);
    func(&context);
    return context.resultCode;
}

struct Window
{
    HWND            handle;
    WNDPROC         nativeHook;
    EventHandler    eventHandler;
    void*           userData;
};

void setNativeWindowHook(Window* window, WNDPROC proc)
{
    window->nativeHook = proc;
}

static KeyCode translateKeyCode(int vkey)
{
    switch( vkey )
    {
    default:
        return KeyCode::Unknown;

#define CASE(FROM, TO) case FROM: return KeyCode::TO;
    CASE('A', A); CASE('B', B); CASE('C', C); CASE('D', D); CASE('E', E);
    CASE('F', F); CASE('G', G); CASE('H', H); CASE('I', I); CASE('J', J);
    CASE('K', K); CASE('L', M); CASE('M', M); CASE('N', N); CASE('O', O);
    CASE('P', P); CASE('Q', Q); CASE('R', R); CASE('S', S); CASE('T', T);
    CASE('U', U); CASE('V', V); CASE('W', W); CASE('X', X); CASE('Y', Y);
    CASE('Z', Z);
#undef CASE

#define CASE(FROM, TO) case VK_##FROM: return KeyCode::TO;
    CASE(SPACE, Space);
#undef CASE
    }
}

static LRESULT CALLBACK windowProc(
    HWND    windowHandle,
    UINT    message,
    WPARAM  wParam,
    LPARAM  lParam)
{
    Window* window = (Window*) GetWindowLongPtrW(windowHandle, GWLP_USERDATA);

    // Give the installed filter a chance to intercept messages.
    // (This is used for ImGui)
    if( window )
    {
        if(auto nativeHook = window->nativeHook)
        {
            auto result = nativeHook(windowHandle, message, wParam, lParam);
            if(result)
                return result;
        }
    }

    auto eventHandler = window ? window->eventHandler : nullptr;

    switch (message)
    {
    case WM_CREATE:
        {
            auto createInfo = (CREATESTRUCTW*) lParam;
            window = (Window*) createInfo->lpCreateParams;
            window->handle = windowHandle;

            SetWindowLongPtrW(windowHandle, GWLP_USERDATA, (LONG)size_t(window));
        }
        break;

    case WM_KEYDOWN:
    case WM_KEYUP:
        {
            int virtualKey = (int) wParam;
            auto keyCode = translateKeyCode(virtualKey);
            if(eventHandler)
            {
                Event event;
                event.window = window;
                event.code = message == WM_KEYDOWN ? EventCode::KeyDown : EventCode::KeyUp;
                event.u.key = keyCode;
                eventHandler(event);
            }
        }
        break;

    case WM_LBUTTONDOWN:
    case WM_LBUTTONUP:
        {
            if(eventHandler)
            {
                Event event;
                event.window = window;
                event.code = message == WM_LBUTTONDOWN ? EventCode::MouseDown : EventCode::MouseUp;
                event.u.mouse.x = (float) GET_X_LPARAM(lParam);
                event.u.mouse.y = (float) GET_Y_LPARAM(lParam);
                eventHandler(event);
            }
        }
        break;

    case WM_MOUSEMOVE:
        {
            if(eventHandler)
            {
                Event event;
                event.window = window;
                event.code = EventCode::MouseMoved;
                event.u.mouse.x = (float) GET_X_LPARAM(lParam);
                event.u.mouse.y = (float) GET_Y_LPARAM(lParam);
                eventHandler(event);
            }
        }
        break;

    case WM_CLOSE:
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProcW(windowHandle, message, wParam, lParam);
}

static ATOM createWindowClassAtom()
{
    WNDCLASSEXW windowClassDesc;
    windowClassDesc.cbSize = sizeof(windowClassDesc);
    windowClassDesc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
    windowClassDesc.lpfnWndProc = &windowProc;
    windowClassDesc.cbClsExtra = 0;
    windowClassDesc.cbWndExtra = 0;
    windowClassDesc.hInstance = (HINSTANCE) GetModuleHandle(0);
    windowClassDesc.hIcon = 0;
    windowClassDesc.hCursor = 0;
    windowClassDesc.hbrBackground = 0;
    windowClassDesc.lpszMenuName = 0;
    windowClassDesc.lpszClassName = L"SlangGraphicsWindow";
    windowClassDesc.hIconSm = 0;
    ATOM windowClassAtom = RegisterClassExW(&windowClassDesc);
    return windowClassAtom;
}

static ATOM getWindowClassAtom()
{
    static ATOM windowClassAtom = createWindowClassAtom();
    return windowClassAtom;
}

Window* createWindow(WindowDesc const& desc)
{
    Window* window = new Window();
    window->handle = nullptr;
    window->nativeHook = nullptr;
    window->eventHandler = desc.eventHandler;
    window->userData = desc.userData;

    OSString windowTitle(desc.title);

    DWORD windowExtendedStyle = 0;
    DWORD windowStyle = 0;

    HINSTANCE instance = (HINSTANCE) GetModuleHandle(0);

    HWND windowHandle = CreateWindowExW(
        windowExtendedStyle,
        (LPWSTR) getWindowClassAtom(),
        windowTitle,
        windowStyle,
        0, 0, // x, y
        desc.width, desc.height,
        NULL, // parent
        NULL, // menu
        instance,
        window);

    if(!windowHandle)
    {
        delete window;
        return nullptr;
    }

    window->handle = windowHandle;
    return window;
}

void showWindow(Window* window)
{
    ShowWindow(window->handle, SW_SHOW);
}

void* getPlatformWindowHandle(Window* window)
{
    return window->handle;
}

void* getUserData(Window* window)
{
    return window->userData;
}

bool dispatchEvents(ApplicationContext* context)
{
    for(;;)
    {
        MSG message;

        int result = PeekMessageW(&message, NULL, 0, 0, PM_REMOVE);
        if (result != 0)
        {
            if (message.message == WM_QUIT)
            {
                context->resultCode = (int)message.wParam;
                return false;
            }

            TranslateMessage(&message);
            DispatchMessageW(&message);
        }
        else
        {
            return true;
        }
    }

}

void exitApplication(ApplicationContext* context, int resultCode)
{
    ExitProcess(resultCode);
}

void log(char const* message, ...)
{
    va_list args;
    va_start(args, message);

    static const int kBufferSize = 1024;
    char messageBuffer[kBufferSize];
    vsnprintf(messageBuffer, kBufferSize - 1, message, args);
    messageBuffer[kBufferSize - 1] = 0;

    va_end(args);

    fputs(messageBuffer, stderr);

    OSString wideMessageBuffer(messageBuffer);
    OutputDebugStringW(wideMessageBuffer);
}

int reportError(char const* message, ...)
{
    va_list args;
    va_start(args, message);

    static const int kBufferSize = 1024;
    char messageBuffer[kBufferSize];
    vsnprintf(messageBuffer, kBufferSize - 1, message, args);
    messageBuffer[kBufferSize - 1] = 0;

    va_end(args);

    fputs(messageBuffer, stderr);

    OSString wideMessageBuffer(messageBuffer);
    OutputDebugStringW(wideMessageBuffer);

    return 1;
}

uint64_t getCurrentTime()
{
    LARGE_INTEGER counter;
    QueryPerformanceCounter(&counter);
    return counter.QuadPart;
}

uint64_t getTimerFrequency()
{
    return gTimerFrequency;
}

#else

// TODO: put an SDL version here

#endif

} // gfx
<commit_msg>Fix a 64-bit issue in our Windows UI code (#887)<commit_after>// window.cpp
#include "window.h"

#include <stdio.h>

#ifdef _MSC_VER
#include <stddef.h>
#if (_MSC_VER < 1900)
#define snprintf sprintf_s
#endif
#endif

#include <stdint.h>

#if _WIN32
#include <Windows.h>
#include <Windowsx.h>
#else
#error "The slang-graphics library currently only supports Windows platforms"
#endif

namespace gfx {

#if _WIN32

struct OSString
{
    OSString(char const* begin, char const* end)
    {
        _initialize(begin, end - begin);
    }

    OSString(char const* begin)
    {
        _initialize(begin, strlen(begin));
    }

    ~OSString()
    {
        free(mBegin);
    }

    operator WCHAR const*()
    {
        return mBegin;
    }

private:
    WCHAR* mBegin;
    WCHAR* mEnd;

    void _initialize(char const* input, size_t inputSize)
    {
        const DWORD dwFlags = 0;
        int outputCodeUnitCount = ::MultiByteToWideChar(CP_UTF8, dwFlags, input, int(inputSize), nullptr, 0);

        WCHAR* buffer = (WCHAR*)malloc(sizeof(WCHAR) * (outputCodeUnitCount + 1));

        ::MultiByteToWideChar(CP_UTF8, dwFlags, input, int(inputSize), buffer, outputCodeUnitCount);
        buffer[outputCodeUnitCount] = 0;

        mBegin = buffer;
        mEnd = buffer + outputCodeUnitCount;
    }
};

struct ApplicationContext
{
    HINSTANCE instance;
    int showCommand = SW_SHOWDEFAULT;
    int resultCode = 0;
};

static uint64_t gTimerFrequency;

static void initApplication(ApplicationContext* context)
{
    LARGE_INTEGER timerFrequency;
    QueryPerformanceFrequency(&timerFrequency);
    gTimerFrequency = timerFrequency.QuadPart;
}

/// Run an application given the specified callback and command-line arguments.
int runApplication(
    ApplicationFunc     func,
    int                 argc,
    char const* const*  argv)
{
    ApplicationContext context;
    context.instance = (HINSTANCE) GetModuleHandle(0);
    initApplication(&context);
    func(&context);
    return context.resultCode;
}

int runWindowsApplication(
    ApplicationFunc     func,
    void*               instance,
    int                 showCommand)
{
    ApplicationContext context;
    context.instance = (HINSTANCE) instance;
    context.showCommand = showCommand;
    initApplication(&context);
    func(&context);
    return context.resultCode;
}

struct Window
{
    HWND            handle;
    WNDPROC         nativeHook;
    EventHandler    eventHandler;
    void*           userData;
};

void setNativeWindowHook(Window* window, WNDPROC proc)
{
    window->nativeHook = proc;
}

static KeyCode translateKeyCode(int vkey)
{
    switch( vkey )
    {
    default:
        return KeyCode::Unknown;

#define CASE(FROM, TO) case FROM: return KeyCode::TO;
    CASE('A', A); CASE('B', B); CASE('C', C); CASE('D', D); CASE('E', E);
    CASE('F', F); CASE('G', G); CASE('H', H); CASE('I', I); CASE('J', J);
    CASE('K', K); CASE('L', M); CASE('M', M); CASE('N', N); CASE('O', O);
    CASE('P', P); CASE('Q', Q); CASE('R', R); CASE('S', S); CASE('T', T);
    CASE('U', U); CASE('V', V); CASE('W', W); CASE('X', X); CASE('Y', Y);
    CASE('Z', Z);
#undef CASE

#define CASE(FROM, TO) case VK_##FROM: return KeyCode::TO;
    CASE(SPACE, Space);
#undef CASE
    }
}

static LRESULT CALLBACK windowProc(
    HWND    windowHandle,
    UINT    message,
    WPARAM  wParam,
    LPARAM  lParam)
{
    Window* window = (Window*) GetWindowLongPtrW(windowHandle, GWLP_USERDATA);

    // Give the installed filter a chance to intercept messages.
    // (This is used for ImGui)
    if( window )
    {
        if(auto nativeHook = window->nativeHook)
        {
            auto result = nativeHook(windowHandle, message, wParam, lParam);
            if(result)
                return result;
        }
    }

    auto eventHandler = window ? window->eventHandler : nullptr;

    switch (message)
    {
    case WM_CREATE:
        {
            auto createInfo = (CREATESTRUCTW*) lParam;
            window = (Window*) createInfo->lpCreateParams;
            window->handle = windowHandle;

            SetWindowLongPtrW(windowHandle, GWLP_USERDATA, (LONG_PTR) window);
        }
        break;

    case WM_KEYDOWN:
    case WM_KEYUP:
        {
            int virtualKey = (int) wParam;
            auto keyCode = translateKeyCode(virtualKey);
            if(eventHandler)
            {
                Event event;
                event.window = window;
                event.code = message == WM_KEYDOWN ? EventCode::KeyDown : EventCode::KeyUp;
                event.u.key = keyCode;
                eventHandler(event);
            }
        }
        break;

    case WM_LBUTTONDOWN:
    case WM_LBUTTONUP:
        {
            if(eventHandler)
            {
                Event event;
                event.window = window;
                event.code = message == WM_LBUTTONDOWN ? EventCode::MouseDown : EventCode::MouseUp;
                event.u.mouse.x = (float) GET_X_LPARAM(lParam);
                event.u.mouse.y = (float) GET_Y_LPARAM(lParam);
                eventHandler(event);
            }
        }
        break;

    case WM_MOUSEMOVE:
        {
            if(eventHandler)
            {
                Event event;
                event.window = window;
                event.code = EventCode::MouseMoved;
                event.u.mouse.x = (float) GET_X_LPARAM(lParam);
                event.u.mouse.y = (float) GET_Y_LPARAM(lParam);
                eventHandler(event);
            }
        }
        break;

    case WM_CLOSE:
        PostQuitMessage(0);
        return 0;
    }

    return DefWindowProcW(windowHandle, message, wParam, lParam);
}

static ATOM createWindowClassAtom()
{
    WNDCLASSEXW windowClassDesc;
    windowClassDesc.cbSize = sizeof(windowClassDesc);
    windowClassDesc.style = CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
    windowClassDesc.lpfnWndProc = &windowProc;
    windowClassDesc.cbClsExtra = 0;
    windowClassDesc.cbWndExtra = 0;
    windowClassDesc.hInstance = (HINSTANCE) GetModuleHandle(0);
    windowClassDesc.hIcon = 0;
    windowClassDesc.hCursor = 0;
    windowClassDesc.hbrBackground = 0;
    windowClassDesc.lpszMenuName = 0;
    windowClassDesc.lpszClassName = L"SlangGraphicsWindow";
    windowClassDesc.hIconSm = 0;
    ATOM windowClassAtom = RegisterClassExW(&windowClassDesc);
    return windowClassAtom;
}

static ATOM getWindowClassAtom()
{
    static ATOM windowClassAtom = createWindowClassAtom();
    return windowClassAtom;
}

Window* createWindow(WindowDesc const& desc)
{
    Window* window = new Window();
    window->handle = nullptr;
    window->nativeHook = nullptr;
    window->eventHandler = desc.eventHandler;
    window->userData = desc.userData;

    OSString windowTitle(desc.title);

    DWORD windowExtendedStyle = 0;
    DWORD windowStyle = 0;

    HINSTANCE instance = (HINSTANCE) GetModuleHandle(0);

    HWND windowHandle = CreateWindowExW(
        windowExtendedStyle,
        (LPWSTR) getWindowClassAtom(),
        windowTitle,
        windowStyle,
        0, 0, // x, y
        desc.width, desc.height,
        NULL, // parent
        NULL, // menu
        instance,
        window);

    if(!windowHandle)
    {
        delete window;
        return nullptr;
    }

    window->handle = windowHandle;
    return window;
}

void showWindow(Window* window)
{
    ShowWindow(window->handle, SW_SHOW);
}

void* getPlatformWindowHandle(Window* window)
{
    return window->handle;
}

void* getUserData(Window* window)
{
    return window->userData;
}

bool dispatchEvents(ApplicationContext* context)
{
    for(;;)
    {
        MSG message;

        int result = PeekMessageW(&message, NULL, 0, 0, PM_REMOVE);
        if (result != 0)
        {
            if (message.message == WM_QUIT)
            {
                context->resultCode = (int)message.wParam;
                return false;
            }

            TranslateMessage(&message);
            DispatchMessageW(&message);
        }
        else
        {
            return true;
        }
    }

}

void exitApplication(ApplicationContext* context, int resultCode)
{
    ExitProcess(resultCode);
}

void log(char const* message, ...)
{
    va_list args;
    va_start(args, message);

    static const int kBufferSize = 1024;
    char messageBuffer[kBufferSize];
    vsnprintf(messageBuffer, kBufferSize - 1, message, args);
    messageBuffer[kBufferSize - 1] = 0;

    va_end(args);

    fputs(messageBuffer, stderr);

    OSString wideMessageBuffer(messageBuffer);
    OutputDebugStringW(wideMessageBuffer);
}

int reportError(char const* message, ...)
{
    va_list args;
    va_start(args, message);

    static const int kBufferSize = 1024;
    char messageBuffer[kBufferSize];
    vsnprintf(messageBuffer, kBufferSize - 1, message, args);
    messageBuffer[kBufferSize - 1] = 0;

    va_end(args);

    fputs(messageBuffer, stderr);

    OSString wideMessageBuffer(messageBuffer);
    OutputDebugStringW(wideMessageBuffer);

    return 1;
}

uint64_t getCurrentTime()
{
    LARGE_INTEGER counter;
    QueryPerformanceCounter(&counter);
    return counter.QuadPart;
}

uint64_t getTimerFrequency()
{
    return gTimerFrequency;
}

#else

// TODO: put an SDL version here

#endif

} // gfx
<|endoftext|>


<commit_before>// $Header$

#include "RenderElement.h"
#include "RGTopFrame.h"
#include "RGEditor.h"

#include <TColor.h>
#include <TCanvas.h>
#include <TGListTree.h>
#include <TGPicture.h>
#include <THashList.h>

#include <algorithm>

using namespace Reve;

//______________________________________________________________________
// RenderElement
//
//

ClassImp(RenderElement)

const TGPicture* RenderElement::fgRnrIcons[4] = { 0 };

RenderElement::RenderElement() :
  fRnrSelf          (kTRUE),
  fRnrChildren        (kTRUE),
  fMainColorPtr        (0),
  fItems               (),
  fParents             (),
  fDestroyOnZeroRefCnt (kTRUE),
  fDenyDestroy         (kFALSE),
  fChildren(0)
{}

RenderElement::RenderElement(Color_t& main_color) :
  fRnrSelf          (kTRUE),
  fRnrChildren        (kTRUE),
  fMainColorPtr        (&main_color),
  fItems               (),
  fParents             (),
  fDestroyOnZeroRefCnt (kTRUE),
  fDenyDestroy         (kFALSE),
  fChildren(0)
{}

RenderElement::~RenderElement()
{
  static const Exc_t _eh("RenderElement::RenderElement ");

  for(sLTI_i i=fItems.begin(); i!=fItems.end(); ++i) {
    DestroyListSubTree(i->fTree, i->fItem);
  }
  RemoveElements();

  for(List_i p=fParents.begin(); p!=fParents.end(); ++p) {
    (*p)->RemoveElementLocal(this);
  }
  fParents.clear();

  for(sLTI_i i=fItems.begin(); i!=fItems.end(); ++i) {
    i->fTree->DeleteItem(i->fItem);
    gClient->NeedRedraw(i->fTree);
  }
}

/**************************************************************************/

void RenderElement::AddParent(RenderElement* re)
{
  fParents.push_back(re);
}

void RenderElement::RemoveParent(RenderElement* re)
{
  static const Exc_t eH("RenderElement::RemoveParent ");

  fParents.remove(re);
  if(fParents.empty() && fDestroyOnZeroRefCnt) {
    // TObject* tobj = GetObject(eH);
    // Warning(eH.Data(), Form("auto-destructing '%s' on zero reference count.", tobj->GetName()));
    gReve->PreDeleteRenderElement(this);
    delete this;
  }
}

/**************************************************************************/

TGListTreeItem* RenderElement::AddIntoListTree(TGListTree* ltree,
					       TGListTreeItem* parent_lti)
{
  static const Exc_t eH("RenderElement::AddIntoListTree ");

  TObject* tobj = GetObject(eH);
  TGListTreeItem* item = ltree->AddItem(parent_lti, tobj->GetName(), this,
					0, 0, kTRUE);
  gClient->NeedRedraw(ltree);
  item->CheckItem(GetRnrSelf());

  if(fMainColorPtr != 0) item->SetColor(GetMainColor());
  item->SetTipText(tobj->GetTitle());

  fItems.insert(ListTreeInfo(ltree, item));

  return item;
}

TGListTreeItem* RenderElement::AddIntoListTree(TGListTree* ltree,
					       RenderElement* parent)
{
  TGListTreeItem* parent_lti = parent ? parent->FindListTreeItem(ltree) : 0;
  return AddIntoListTree(ltree, parent_lti);
}

Bool_t RenderElement::RemoveFromListTree(TGListTree* ltree)
{
  sLTI_i i = FindItem(ltree);
  if(i != fItems.end()) {
    ltree->DeleteItem(i->fItem);
    fItems.erase(i);
    gClient->NeedRedraw(ltree);
    return kTRUE;
  } else {
    return kFALSE;
  }
}

Bool_t RenderElement::RemoveFromListTree(TGListTree* ltree,
					 TGListTreeItem* parent_lti)
{
  sLTI_i i = FindItem(ltree, parent_lti);
  if(i != fItems.end()) {
    ltree->DeleteItem(i->fItem);
    fItems.erase(i);
    gClient->NeedRedraw(ltree);
    return kTRUE;
  } else {
    return kFALSE;
  }
}

/**************************************************************************/

RenderElement::sLTI_i RenderElement::FindItem(TGListTree* ltree)
{
  for(sLTI_i i = fItems.begin(); i != fItems.end(); ++i)
    if(i->fTree == ltree)
      return i;
  return fItems.end();
}

RenderElement::sLTI_i RenderElement::FindItem(TGListTree* ltree,
					      TGListTreeItem* parent_lti)
{
  for(sLTI_i i = fItems.begin(); i != fItems.end(); ++i)
    if(i->fTree == ltree && i->fItem->GetParent() == parent_lti)
      return i;
  return fItems.end();
}

TGListTreeItem* RenderElement::FindListTreeItem(TGListTree* ltree)
{
  for(sLTI_i i = fItems.begin(); i != fItems.end(); ++i)
    if(i->fTree == ltree)
      return i->fItem;
  return 0;
}

TGListTreeItem* RenderElement::FindListTreeItem(TGListTree* ltree,
						TGListTreeItem* parent_lti)
{
  for(sLTI_i i = fItems.begin(); i != fItems.end(); ++i)
    if(i->fTree == ltree && i->fItem->GetParent() == parent_lti)
      return i->fItem;
  return 0;
}

/**************************************************************************/

void RenderElement::UpdateItems()
{
  static const Exc_t eH("RenderElement::UpdateItems ");

  TObject* tobj = GetObject(eH);
  for(sLTI_i i=fItems.begin(); i!=fItems.end(); ++i) {
    i->fItem->Rename(tobj->GetName());
    i->fItem->SetTipText(tobj->GetTitle());
    i->fItem->CheckItem(fRnrSelf);
    if(fMainColorPtr != 0) i->fItem->SetColor(GetMainColor());
    gClient->NeedRedraw(i->fTree);
  }
}

/**************************************************************************/

TObject* RenderElement::GetObject(Exc_t eh)
{
  TObject* obj = dynamic_cast<TObject*>(this);
  if(obj == 0)
    throw(eh + "not a TObject.");
  return obj;
}

void RenderElement::SpawnEditor()
{
  gReve->EditRenderElement(this);
}

void RenderElement::ExportToCINT(Text_t* var_name)
{
  static const Exc_t eH("RenderElement::ExportToCINT ");

  const char* cname = IsA()->GetName();
  gROOT->ProcessLine(Form("%s* %s = (%s*)0x%lx;", cname, var_name, cname, this));
}

/**************************************************************************/

void RenderElement::PadPaint(Option_t* option)
{
  if ( GetRnrSelf() && GetObject() )
    GetObject()->Paint(option);

  if (GetRnrChildren()) {
    for(List_i i=BeginChildren(); i!=EndChildren(); ++i) {
      (*i)->PadPaint(option);
    }
  }
}

/**************************************************************************/

void RenderElement::SetRnrSelf(Bool_t rnr)
{
  if(rnr != fRnrSelf)
  {
    fRnrSelf = rnr;

    for(sLTI_i i=fItems.begin(); i!=fItems.end(); ++i)
    {
      if (i->fItem->IsChecked() != rnr) {
        i->fItem->SetCheckBoxPictures(GetCheckBoxPicture(1,fRnrChildren), GetCheckBoxPicture(0,fRnrChildren));
#if ROOT_VERSION_CODE <= ROOT_VERSION(5,14,0)
        // cover undesired behavior TGListTree::UpdateChecked
	if(i->fItem->GetParent()) {
	  RenderElement* p = (RenderElement*) i->fItem->GetParent()->GetUserData();
	  if(p)
	    i->fItem->GetParent()->SetCheckBoxPictures(GetCheckBoxPicture(1, p->GetRnrChildren()),
						       GetCheckBoxPicture(0, p->GetRnrChildren()));
	}
#endif
        i->fItem->CheckItem(fRnrSelf);
        gClient->NeedRedraw(i->fTree);
      }
    }
  }
}

void RenderElement::SetRnrChildren(Bool_t rnr)
{
  if(rnr != fRnrChildren)
  {
    fRnrChildren = rnr;

    for(sLTI_i i=fItems.begin(); i!=fItems.end(); ++i)
    {
      i->fItem->SetCheckBoxPictures(GetCheckBoxPicture(fRnrSelf, fRnrChildren), GetCheckBoxPicture(fRnrSelf,fRnrChildren));
      gClient->NeedRedraw(i->fTree);
    }
  }
}

void RenderElement::ToggleRnrState()
{
  if (fRnrSelf || fRnrChildren)
    fRnrSelf = fRnrChildren = kFALSE;
  else
    fRnrSelf = fRnrChildren = kTRUE;

  for (sLTI_i i=fItems.begin(); i!=fItems.end(); ++i)
  {
    i->fItem->SetCheckBoxPictures(GetCheckBoxPicture(1,1), GetCheckBoxPicture(0,0));
    i->fItem->CheckItem(fRnrSelf);

#if ROOT_VERSION_CODE <= ROOT_VERSION(5,14,0)
    // cover undesired behavior TGListTree::UpdateChecked
    if(i->fItem->GetParent()) {
      RenderElement* p = (RenderElement*) i->fItem->GetParent()->GetUserData();
      if(p)
	i->fItem->GetParent()->SetCheckBoxPictures(GetCheckBoxPicture(1, p->GetRnrChildren()),
						   GetCheckBoxPicture(0, p->GetRnrChildren()));
    }
#endif
    gClient->NeedRedraw(i->fTree);
  }
}

/**************************************************************************/

void RenderElement::SetMainColor(Color_t color)
{
  Color_t oldcol = GetMainColor();
  for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
    if((*i)->GetMainColor() == oldcol) (*i)->SetMainColor(color);
  }

  if (fMainColorPtr) {
    *fMainColorPtr = color;
    for(sLTI_i i=fItems.begin(); i!=fItems.end(); ++i) {
      if(i->fItem->GetColor() != color) {
        i->fItem->SetColor(GetMainColor());
        gClient->NeedRedraw(i->fTree);
      }
    }
  }
}

void RenderElement::SetMainColor(Pixel_t pixel)
{
  SetMainColor(Color_t(TColor::GetColor(pixel)));
}

/**************************************************************************/

void RenderElement::AddElement(RenderElement* el)
{
  fChildren.push_back(el);
  el->AddParent(this);
}

void RenderElement::RemoveElement(RenderElement* el)
{
   el->RemoveParent(this);
   RemoveElementLocal(el);
}

void RenderElement::RemoveElementLocal(RenderElement* el)
{
  fChildren.remove(el);
}

void RenderElement::RemoveElements()
{
  for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
    (*i)->RemoveParent(this);
  }
  fChildren.clear();
}

/**************************************************************************/

Int_t RenderElement::ExpandIntoListTree(TGListTree* ltree,
						TGListTreeItem* parent)
{
  // Populates parent with elements.
  // parent must be an already existing representation of *this*.
  // Returns number of inserted elements.
  // If parent already has children, it does nothing.
  //
  // RnrEl can be inserted in a list-tree several times, thus we can not
  // search through fItems to get parent here.
  // Anyhow, it is probably known as it must have been selected by the user.

  if(parent->GetFirstChild() != 0)
    return 0;
  Int_t n = 0;
  for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
    (*i)->AddIntoListTree(ltree, parent);
    ++n;
  }
  return n;
}

/**************************************************************************/

void RenderElement::EnableListElements()
{
  for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
    (*i)->SetRnrSelf(kTRUE);

  gReve->Redraw3D();
}

void RenderElement::DisableListElements()
{
  for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
    (*i)->SetRnrSelf(kFALSE);

  gReve->Redraw3D();
}

/**************************************************************************/

Int_t RenderElement::DestroyListSubTree(TGListTree* ltree,
						TGListTreeItem* parent)
{
  Int_t n = 0;
  TGListTreeItem* i = parent->GetFirstChild();
  while(i != 0) {
    n += DestroyListSubTree(ltree, i);
    RenderElement* re = (RenderElement*) i->GetUserData();
    i = i->GetNextSibling();
    re->RemoveFromListTree(ltree, parent);
  }
  return n;
}

void RenderElement::Destroy()
{
  static const Exc_t eH("RenderElement::Destroy ");

  if(fDenyDestroy)
    throw(eH + "this object is protected against destruction.");

  gReve->PreDeleteRenderElement(this);
  delete this;
  gReve->Redraw3D();
}

void RenderElement::DestroyElements()
{
  static const Exc_t eH("RenderElement::DestroyElements ");

  while( ! fChildren.empty()) {
    RenderElement* c = fChildren.front();
    try {
      c->Destroy();
    }
    catch(Exc_t exc) {
      Warning(eH.Data(), Form("element destruction failed: '%s'.", exc.Data()));
      RemoveElement(c);
    }
  }
}

const TGPicture*  RenderElement::GetCheckBoxPicture(Bool_t rnrSelf, Bool_t rnrDaughters)
{
  Int_t idx = 0;
  if(rnrSelf) idx = 2;
  if( rnrDaughters ) idx ++;

  return fgRnrIcons[idx];
}

/**************************************************************************/

ClassImp(RenderElementObjPtr)

RenderElementObjPtr::RenderElementObjPtr(TObject* obj, Bool_t own) :
  RenderElement(),
  fObject(obj),
  fOwnObject(own)
{}

RenderElementObjPtr::RenderElementObjPtr(TObject* obj, Color_t& mainColor, Bool_t own) :
  RenderElement(mainColor),
  fObject(obj),
  fOwnObject(own)
{}

TObject* RenderElementObjPtr::GetObject(Reve::Exc_t eh)
{
  if(fObject == 0)
    throw(eh + "fObject not set.");
  return fObject;
}

void RenderElementObjPtr::ExportToCINT(Text_t* var_name)
{
  static const Exc_t eH("RenderElementObjPtr::ExportToCINT ");

  TObject* obj = GetObject(eH);
  const char* cname = obj->IsA()->GetName();
  gROOT->ProcessLine(Form("%s* %s = (%s*)0x%lx;", cname, var_name, cname, obj));
}

RenderElementObjPtr::~RenderElementObjPtr()
{
  if(fOwnObject)
    delete fObject;
}

/**************************************************************************/

ClassImp(RenderElementList)

RenderElementList::RenderElementList(const Text_t* n, const Text_t* t, Bool_t doColor) :
  RenderElement(),
  TNamed(n, t),
  fColor(0),
  fDoColor(doColor)
{
  if(fDoColor) {
    SetMainColorPtr(&fColor);
  }
}

/**************************************************************************/

ClassImp(PadPrimitive)

PadPrimitive::PadPrimitive(const Text_t* n, const Text_t* t) :
  RenderElement(),
  TNamed(n, t)
{}

void PadPrimitive::Paint(Option_t* option)
{
  if (fRnrChildren)
  {
    for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
      (*i)->PadPaint(option);
  }
}

<commit_msg>Setup check-box pictures when inserting in a list-tree.<commit_after>// $Header$

#include "RenderElement.h"
#include "RGTopFrame.h"
#include "RGEditor.h"

#include <TColor.h>
#include <TCanvas.h>
#include <TGListTree.h>
#include <TGPicture.h>
#include <THashList.h>

#include <algorithm>

using namespace Reve;

//______________________________________________________________________
// RenderElement
//
//

ClassImp(RenderElement)

const TGPicture* RenderElement::fgRnrIcons[4] = { 0 };

RenderElement::RenderElement() :
  fRnrSelf          (kTRUE),
  fRnrChildren        (kTRUE),
  fMainColorPtr        (0),
  fItems               (),
  fParents             (),
  fDestroyOnZeroRefCnt (kTRUE),
  fDenyDestroy         (kFALSE),
  fChildren(0)
{}

RenderElement::RenderElement(Color_t& main_color) :
  fRnrSelf          (kTRUE),
  fRnrChildren        (kTRUE),
  fMainColorPtr        (&main_color),
  fItems               (),
  fParents             (),
  fDestroyOnZeroRefCnt (kTRUE),
  fDenyDestroy         (kFALSE),
  fChildren(0)
{}

RenderElement::~RenderElement()
{
  static const Exc_t _eh("RenderElement::RenderElement ");

  for(sLTI_i i=fItems.begin(); i!=fItems.end(); ++i) {
    DestroyListSubTree(i->fTree, i->fItem);
  }
  RemoveElements();

  for(List_i p=fParents.begin(); p!=fParents.end(); ++p) {
    (*p)->RemoveElementLocal(this);
  }
  fParents.clear();

  for(sLTI_i i=fItems.begin(); i!=fItems.end(); ++i) {
    i->fTree->DeleteItem(i->fItem);
    gClient->NeedRedraw(i->fTree);
  }
}

/**************************************************************************/

void RenderElement::AddParent(RenderElement* re)
{
  fParents.push_back(re);
}

void RenderElement::RemoveParent(RenderElement* re)
{
  static const Exc_t eH("RenderElement::RemoveParent ");

  fParents.remove(re);
  if(fParents.empty() && fDestroyOnZeroRefCnt) {
    // TObject* tobj = GetObject(eH);
    // Warning(eH.Data(), Form("auto-destructing '%s' on zero reference count.", tobj->GetName()));
    gReve->PreDeleteRenderElement(this);
    delete this;
  }
}

/**************************************************************************/

TGListTreeItem* RenderElement::AddIntoListTree(TGListTree* ltree,
					       TGListTreeItem* parent_lti)
{
  static const Exc_t eH("RenderElement::AddIntoListTree ");

  TObject* tobj = GetObject(eH);
  TGListTreeItem* item = ltree->AddItem(parent_lti, tobj->GetName(), this,
					0, 0, kTRUE);
  item->SetCheckBoxPictures(GetCheckBoxPicture(1, fRnrChildren),
			    GetCheckBoxPicture(0, fRnrChildren));
  item->CheckItem(fRnrSelf);

  if(fMainColorPtr != 0) item->SetColor(GetMainColor());
  item->SetTipText(tobj->GetTitle());

  fItems.insert(ListTreeInfo(ltree, item));

  gClient->NeedRedraw(ltree);

  return item;
}

TGListTreeItem* RenderElement::AddIntoListTree(TGListTree* ltree,
					       RenderElement* parent)
{
  TGListTreeItem* parent_lti = parent ? parent->FindListTreeItem(ltree) : 0;
  return AddIntoListTree(ltree, parent_lti);
}

Bool_t RenderElement::RemoveFromListTree(TGListTree* ltree)
{
  sLTI_i i = FindItem(ltree);
  if(i != fItems.end()) {
    ltree->DeleteItem(i->fItem);
    fItems.erase(i);
    gClient->NeedRedraw(ltree);
    return kTRUE;
  } else {
    return kFALSE;
  }
}

Bool_t RenderElement::RemoveFromListTree(TGListTree* ltree,
					 TGListTreeItem* parent_lti)
{
  sLTI_i i = FindItem(ltree, parent_lti);
  if(i != fItems.end()) {
    ltree->DeleteItem(i->fItem);
    fItems.erase(i);
    gClient->NeedRedraw(ltree);
    return kTRUE;
  } else {
    return kFALSE;
  }
}

/**************************************************************************/

RenderElement::sLTI_i RenderElement::FindItem(TGListTree* ltree)
{
  for(sLTI_i i = fItems.begin(); i != fItems.end(); ++i)
    if(i->fTree == ltree)
      return i;
  return fItems.end();
}

RenderElement::sLTI_i RenderElement::FindItem(TGListTree* ltree,
					      TGListTreeItem* parent_lti)
{
  for(sLTI_i i = fItems.begin(); i != fItems.end(); ++i)
    if(i->fTree == ltree && i->fItem->GetParent() == parent_lti)
      return i;
  return fItems.end();
}

TGListTreeItem* RenderElement::FindListTreeItem(TGListTree* ltree)
{
  for(sLTI_i i = fItems.begin(); i != fItems.end(); ++i)
    if(i->fTree == ltree)
      return i->fItem;
  return 0;
}

TGListTreeItem* RenderElement::FindListTreeItem(TGListTree* ltree,
						TGListTreeItem* parent_lti)
{
  for(sLTI_i i = fItems.begin(); i != fItems.end(); ++i)
    if(i->fTree == ltree && i->fItem->GetParent() == parent_lti)
      return i->fItem;
  return 0;
}

/**************************************************************************/

void RenderElement::UpdateItems()
{
  static const Exc_t eH("RenderElement::UpdateItems ");

  TObject* tobj = GetObject(eH);
  for(sLTI_i i=fItems.begin(); i!=fItems.end(); ++i) {
    i->fItem->Rename(tobj->GetName());
    i->fItem->SetTipText(tobj->GetTitle());
    i->fItem->CheckItem(fRnrSelf);
    if(fMainColorPtr != 0) i->fItem->SetColor(GetMainColor());
    gClient->NeedRedraw(i->fTree);
  }
}

/**************************************************************************/

TObject* RenderElement::GetObject(Exc_t eh)
{
  TObject* obj = dynamic_cast<TObject*>(this);
  if(obj == 0)
    throw(eh + "not a TObject.");
  return obj;
}

void RenderElement::SpawnEditor()
{
  gReve->EditRenderElement(this);
}

void RenderElement::ExportToCINT(Text_t* var_name)
{
  static const Exc_t eH("RenderElement::ExportToCINT ");

  const char* cname = IsA()->GetName();
  gROOT->ProcessLine(Form("%s* %s = (%s*)0x%lx;", cname, var_name, cname, this));
}

/**************************************************************************/

void RenderElement::PadPaint(Option_t* option)
{
  if (GetRnrSelf() && GetObject())
    GetObject()->Paint(option);

  if (GetRnrChildren()) {
    for(List_i i=BeginChildren(); i!=EndChildren(); ++i) {
      (*i)->PadPaint(option);
    }
  }
}

/**************************************************************************/

void RenderElement::SetRnrSelf(Bool_t rnr)
{
  if(rnr != fRnrSelf)
  {
    fRnrSelf = rnr;

    for(sLTI_i i=fItems.begin(); i!=fItems.end(); ++i)
    {
      if(i->fItem->IsChecked() != rnr) {
        i->fItem->SetCheckBoxPictures(GetCheckBoxPicture(1, fRnrChildren),
				      GetCheckBoxPicture(0, fRnrChildren));
#if ROOT_VERSION_CODE <= ROOT_VERSION(5,14,0)
        // cover undesired behavior TGListTree::UpdateChecked
	if(i->fItem->GetParent()) {
	  RenderElement* p = (RenderElement*) i->fItem->GetParent()->GetUserData();
	  if(p)
	    i->fItem->GetParent()->SetCheckBoxPictures(GetCheckBoxPicture(1, p->GetRnrChildren()),
						       GetCheckBoxPicture(0, p->GetRnrChildren()));
	}
#endif
        i->fItem->CheckItem(fRnrSelf);
        gClient->NeedRedraw(i->fTree);
      }
    }
  }
}

void RenderElement::SetRnrChildren(Bool_t rnr)
{
  if(rnr != fRnrChildren)
  {
    fRnrChildren = rnr;

    for(sLTI_i i=fItems.begin(); i!=fItems.end(); ++i)
    {
      i->fItem->SetCheckBoxPictures(GetCheckBoxPicture(fRnrSelf, fRnrChildren),
				    GetCheckBoxPicture(fRnrSelf, fRnrChildren));
      gClient->NeedRedraw(i->fTree);
    }
  }
}

void RenderElement::ToggleRnrState()
{
  if (fRnrSelf || fRnrChildren)
    fRnrSelf = fRnrChildren = kFALSE;
  else
    fRnrSelf = fRnrChildren = kTRUE;

  for (sLTI_i i=fItems.begin(); i!=fItems.end(); ++i)
  {
    i->fItem->SetCheckBoxPictures(GetCheckBoxPicture(1,1), GetCheckBoxPicture(0,0));
    i->fItem->CheckItem(fRnrSelf);

#if ROOT_VERSION_CODE <= ROOT_VERSION(5,14,0)
    // cover undesired behavior TGListTree::UpdateChecked
    if(i->fItem->GetParent()) {
      RenderElement* p = (RenderElement*) i->fItem->GetParent()->GetUserData();
      if(p)
	i->fItem->GetParent()->SetCheckBoxPictures(GetCheckBoxPicture(1, p->GetRnrChildren()),
						   GetCheckBoxPicture(0, p->GetRnrChildren()));
    }
#endif
    gClient->NeedRedraw(i->fTree);
  }
}

/**************************************************************************/

void RenderElement::SetMainColor(Color_t color)
{
  Color_t oldcol = GetMainColor();
  for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
    if((*i)->GetMainColor() == oldcol) (*i)->SetMainColor(color);
  }

  if (fMainColorPtr) {
    *fMainColorPtr = color;
    for(sLTI_i i=fItems.begin(); i!=fItems.end(); ++i) {
      if(i->fItem->GetColor() != color) {
        i->fItem->SetColor(GetMainColor());
        gClient->NeedRedraw(i->fTree);
      }
    }
  }
}

void RenderElement::SetMainColor(Pixel_t pixel)
{
  SetMainColor(Color_t(TColor::GetColor(pixel)));
}

/**************************************************************************/

void RenderElement::AddElement(RenderElement* el)
{
  fChildren.push_back(el);
  el->AddParent(this);
}

void RenderElement::RemoveElement(RenderElement* el)
{
   el->RemoveParent(this);
   RemoveElementLocal(el);
}

void RenderElement::RemoveElementLocal(RenderElement* el)
{
  fChildren.remove(el);
}

void RenderElement::RemoveElements()
{
  for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
    (*i)->RemoveParent(this);
  }
  fChildren.clear();
}

/**************************************************************************/

Int_t RenderElement::ExpandIntoListTree(TGListTree* ltree,
						TGListTreeItem* parent)
{
  // Populates parent with elements.
  // parent must be an already existing representation of *this*.
  // Returns number of inserted elements.
  // If parent already has children, it does nothing.
  //
  // RnrEl can be inserted in a list-tree several times, thus we can not
  // search through fItems to get parent here.
  // Anyhow, it is probably known as it must have been selected by the user.

  if(parent->GetFirstChild() != 0)
    return 0;
  Int_t n = 0;
  for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i) {
    (*i)->AddIntoListTree(ltree, parent);
    ++n;
  }
  return n;
}

/**************************************************************************/

void RenderElement::EnableListElements()
{
  for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
    (*i)->SetRnrSelf(kTRUE);

  gReve->Redraw3D();
}

void RenderElement::DisableListElements()
{
  for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
    (*i)->SetRnrSelf(kFALSE);

  gReve->Redraw3D();
}

/**************************************************************************/

Int_t RenderElement::DestroyListSubTree(TGListTree* ltree,
						TGListTreeItem* parent)
{
  Int_t n = 0;
  TGListTreeItem* i = parent->GetFirstChild();
  while(i != 0) {
    n += DestroyListSubTree(ltree, i);
    RenderElement* re = (RenderElement*) i->GetUserData();
    i = i->GetNextSibling();
    re->RemoveFromListTree(ltree, parent);
  }
  return n;
}

void RenderElement::Destroy()
{
  static const Exc_t eH("RenderElement::Destroy ");

  if(fDenyDestroy)
    throw(eH + "this object is protected against destruction.");

  gReve->PreDeleteRenderElement(this);
  delete this;
  gReve->Redraw3D();
}

void RenderElement::DestroyElements()
{
  static const Exc_t eH("RenderElement::DestroyElements ");

  while( ! fChildren.empty()) {
    RenderElement* c = fChildren.front();
    try {
      c->Destroy();
    }
    catch(Exc_t exc) {
      Warning(eH.Data(), Form("element destruction failed: '%s'.", exc.Data()));
      RemoveElement(c);
    }
  }
}

const TGPicture* RenderElement::GetCheckBoxPicture(Bool_t rnrSelf, Bool_t rnrDaughters)
{
  Int_t idx = 0;
  if(rnrSelf)       idx = 2;
  if(rnrDaughters ) idx++;

  return fgRnrIcons[idx];
}

/**************************************************************************/

ClassImp(RenderElementObjPtr)

RenderElementObjPtr::RenderElementObjPtr(TObject* obj, Bool_t own) :
  RenderElement(),
  fObject(obj),
  fOwnObject(own)
{}

RenderElementObjPtr::RenderElementObjPtr(TObject* obj, Color_t& mainColor, Bool_t own) :
  RenderElement(mainColor),
  fObject(obj),
  fOwnObject(own)
{}

TObject* RenderElementObjPtr::GetObject(Reve::Exc_t eh)
{
  if(fObject == 0)
    throw(eh + "fObject not set.");
  return fObject;
}

void RenderElementObjPtr::ExportToCINT(Text_t* var_name)
{
  static const Exc_t eH("RenderElementObjPtr::ExportToCINT ");

  TObject* obj = GetObject(eH);
  const char* cname = obj->IsA()->GetName();
  gROOT->ProcessLine(Form("%s* %s = (%s*)0x%lx;", cname, var_name, cname, obj));
}

RenderElementObjPtr::~RenderElementObjPtr()
{
  if(fOwnObject)
    delete fObject;
}

/**************************************************************************/

ClassImp(RenderElementList)

RenderElementList::RenderElementList(const Text_t* n, const Text_t* t, Bool_t doColor) :
  RenderElement(),
  TNamed(n, t),
  fColor(0),
  fDoColor(doColor)
{
  if(fDoColor) {
    SetMainColorPtr(&fColor);
  }
}

/**************************************************************************/

ClassImp(PadPrimitive)

PadPrimitive::PadPrimitive(const Text_t* n, const Text_t* t) :
  RenderElement(),
  TNamed(n, t)
{}

void PadPrimitive::Paint(Option_t* option)
{
  if (fRnrChildren)
  {
    for(List_i i=fChildren.begin(); i!=fChildren.end(); ++i)
      (*i)->PadPaint(option);
  }
}

<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *
 * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for          *
 * full copyright notice.                                                 *
 **************************************************************************/

class TEveProjectionManager;
class TEveGeoShape;
class TEveUtil;

Bool_t gCenterProjectionsAtPrimaryVertex = kFALSE;

void alieve_online_init()
{
  if (gROOT->LoadMacro("MultiView.C++") != 0)
  {
    gEnv->SetValue("Root.Stacktrace", "no");
    Fatal("alieve_online.C", "Failed loading MultiView.C in compiled mode.");
  }

  TEveUtil::AssertMacro("VizDB_scan.C");

  TEveBrowser *browser = gEve->GetBrowser();
  browser->ShowCloseTab(kFALSE);

  // Gentle-geom loading changes gGeoManager.
  TEveGeoManagerHolder mgrRestore;

  gMultiView = new MultiView;

  TEveUtil::LoadMacro("geom_gentle.C");
  gMultiView->InitGeomGentle(geom_gentle(),
                             geom_gentle_rphi(),
                             geom_gentle_rhoz());

  // See visscan_init.C for how to add TRD / MUON geometry.

  //============================================================================
  // Standard macros to execute -- not all are enabled by default.
  //============================================================================

  AliEveMacroExecutor *exec = AliEveEventManager::GetMaster()->GetExecutor();

  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX",         "primary_vertex.C", "primary_vertex",             "",                kTRUE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX Ellipse", "primary_vertex.C", "primary_vertex_ellipse",     "",                kTRUE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX Box",     "primary_vertex.C", "primary_vertex_box",         "kFALSE, 3, 3, 3", kFALSE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX",         "primary_vertex.C", "primary_vertex_spd",         "",                kTRUE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX Ellipse", "primary_vertex.C", "primary_vertex_ellipse_spd", "",                kTRUE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX Box",     "primary_vertex.C", "primary_vertex_box_spd",     "kFALSE, 3, 3, 3", kFALSE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX",         "primary_vertex.C", "primary_vertex_tpc",         "",                kFALSE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX Ellipse", "primary_vertex.C", "primary_vertex_ellipse_tpc", "",                kFALSE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX Box",     "primary_vertex.C", "primary_vertex_box_tpc",     "kFALSE, 3, 3, 3", kFALSE));

  exec->AddMacro(new AliEveMacro(AliEveMacro::kRunLoader, "REC Clus ITS",   "its_clusters.C++",   "its_clusters"));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kRunLoader, "REC Clus TPC",   "tpc_clusters.C++",   "tpc_clusters"));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kRunLoader, "REC Clus TOF",   "tof_clusters.C++",   "tof_clusters"));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kRunLoader, "REC Clus HMPID", "hmpid_clusters.C++", "hmpid_clusters"));

  exec->AddMacro(new AliEveMacro(AliEveMacro::kRunLoader, "REC Clus TOF",   "emcal_digits.C++",   "emcal_digits"));

  exec->AddMacro(new AliEveMacro(AliEveMacro::kRawReader, "RAW ITS",     "its_raw.C",     "its_raw"));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kRawReader, "RAW TPC",     "tpc_raw.C",     "tpc_raw"));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kRawReader, "RAW TOF",     "tof_raw.C",     "tof_raw"));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kRawReader, "RAW VZERO",   "vzero_raw.C",   "vzero_raw"));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kRawReader, "RAW ACORDE",  "acorde_raw.C",  "acorde_raw"));

  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC Track", "esd_tracks.C", "esd_tracks",             "", kFALSE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC Track", "esd_tracks.C", "esd_tracks_MI",          "", kFALSE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC Track", "esd_tracks.C", "esd_tracks_by_category", "", kTRUE));

  // ???
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC TRD", "trd_detectors.C++", "trd_detectors",         "", kFALSE));
  // trd_tracks disabled due to memory leaks

  //----------------------------------------------------------------------------

  slot = TEveWindow::CreateWindowInTab(browser->GetTabRight());
  slot->StartEmbedding();
  AliEveMacroExecutorWindow* exewin = new AliEveMacroExecutorWindow(exec);
  slot->StopEmbedding("DataSelection");
  exewin->PopulateMacros();

  //============================================================================
  // Final GUI setup
  //============================================================================

  browser->GetTabRight()->SetTab(1);

  browser->StartEmbedding(TRootBrowser::kBottom);
  new AliEveEventManagerWindow(AliEveEventManager::GetMaster());
  browser->StopEmbedding("EventCtrl");

  browser->MoveResize(0, 0, gClient->GetDisplayWidth(),
		      gClient->GetDisplayHeight() - 32);

  gEve->GetViewers()->SwitchColorSet();

  TString autoRun(gSystem->Getenv("ONLINERECO_AUTORUN"));
  if (autoRun == "1" || autoRun.CompareTo("true", TString::kIgnoreCase) == 0)
  {
    AliEveEventManager::GetMaster()->SetAutoLoad(kTRUE);
  }

  {
    TGTab *tab = gEve->GetBrowser()->GetTab(2);

    TGHorizontalFrame *hf = (TGHorizontalFrame*) tab->GetParent();
    TGVerticalFrame   *vf = (TGVerticalFrame*)   hf ->GetParent();

    hf->Resize(hf->GetWidth(), hf->GetHeight() + 80);
    vf->Layout();
  }

  gEve->FullRedraw3D(kTRUE);

  TGLViewer *glv = gMultiView->f3DView->GetGLViewer();
  glv->CurrentCamera().RotateRad(-0.4, 1);
  glv->DoDraw();
}

Int_t      g_pic_id  = 0;
Int_t      g_pic_max = 10;
TTimeStamp g_pic_prev(0, 0);

void alieve_online_on_new_event()
{
  AliESDEvent* esd = AliEveEventManager::AssertESD();
  Double_t x[3];
  esd->GetPrimaryVertex()->GetXYZ(x);

  TEveElement* top = gEve->GetCurrentEvent();

  gMultiView->DestroyEventRPhi();
  if (gCenterProjectionsAtPrimaryVertex)
    gMultiView->SetCenterRPhi(x[0], x[1], x[2]);
  gMultiView->ImportEventRPhi(top);

  gMultiView->DestroyEventRhoZ();
  if (gCenterProjectionsAtPrimaryVertex)
    gMultiView->SetCenterRhoZ(x[0], x[1], x[2]);
  gMultiView->ImportEventRhoZ(top);

  // Register image to amore.
  const TString pichost("aldaqacrs3");
  TTimeStamp now;
  Double_t delta = now.AsDouble() - g_pic_prev.AsDouble();

  printf("Pre image dump: host='%s', delta=%f.\n",
	 gSystem->HostName(), delta);

  if (pichost == gSystem->HostName() && delta >= 30)
  {
    TString id;      id.Form("online-viz-%03d", g_pic_id);
    TString pic(id); pic += ".png";

    printf("In image dump: file='%s'.\n", pic.Data());

    gEve->GetBrowser()->RaiseWindow();
    gEve->FullRedraw3D();
    gSystem->ProcessEvents();

    Int_t status;

    status = gSystem->Exec(TString::Format("xwd -id %u | convert - %s",
			   gEve->GetBrowser()->GetId(), pic.Data()));

    printf("Post capture -- status=%d.\n", status);

    status = gSystem->Exec(TString::Format("SendImageToAmore %s %s %d",
		          id.Data(), pic.Data(),
		          AliEveEventManager::AssertRawReader()->GetRunNumber()));

    printf("Post AMORE reg -- status=%d, run=%d.\n", status,
	   AliEveEventManager::AssertRawReader()->GetRunNumber());

    if (++g_pic_id >= g_pic_max)
      g_pic_id = 0;
    g_pic_prev.Set();
  }
}
<commit_msg>Add trd_clusters.C to alieve_online.C.<commit_after>/**************************************************************************
 * Copyright(c) 1998-2008, ALICE Experiment at CERN, all rights reserved. *
 * See http://aliceinfo.cern.ch/Offline/AliRoot/License.html for          *
 * full copyright notice.                                                 *
 **************************************************************************/

class TEveProjectionManager;
class TEveGeoShape;
class TEveUtil;

Bool_t gCenterProjectionsAtPrimaryVertex = kFALSE;

void alieve_online_init()
{
  if (gROOT->LoadMacro("MultiView.C++") != 0)
  {
    gEnv->SetValue("Root.Stacktrace", "no");
    Fatal("alieve_online.C", "Failed loading MultiView.C in compiled mode.");
  }

  TEveUtil::AssertMacro("VizDB_scan.C");

  TEveBrowser *browser = gEve->GetBrowser();
  browser->ShowCloseTab(kFALSE);

  // Gentle-geom loading changes gGeoManager.
  TEveGeoManagerHolder mgrRestore;

  gMultiView = new MultiView;

  TEveUtil::LoadMacro("geom_gentle.C");
  gMultiView->InitGeomGentle(geom_gentle(),
                             geom_gentle_rphi(),
                             geom_gentle_rhoz());

  // See visscan_init.C for how to add TRD / MUON geometry.

  //============================================================================
  // Standard macros to execute -- not all are enabled by default.
  //============================================================================

  AliEveMacroExecutor *exec = AliEveEventManager::GetMaster()->GetExecutor();

  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX",         "primary_vertex.C", "primary_vertex",             "",                kTRUE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX Ellipse", "primary_vertex.C", "primary_vertex_ellipse",     "",                kTRUE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX Box",     "primary_vertex.C", "primary_vertex_box",         "kFALSE, 3, 3, 3", kFALSE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX",         "primary_vertex.C", "primary_vertex_spd",         "",                kTRUE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX Ellipse", "primary_vertex.C", "primary_vertex_ellipse_spd", "",                kTRUE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX Box",     "primary_vertex.C", "primary_vertex_box_spd",     "kFALSE, 3, 3, 3", kFALSE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX",         "primary_vertex.C", "primary_vertex_tpc",         "",                kFALSE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX Ellipse", "primary_vertex.C", "primary_vertex_ellipse_tpc", "",                kFALSE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC PVTX Box",     "primary_vertex.C", "primary_vertex_box_tpc",     "kFALSE, 3, 3, 3", kFALSE));

  exec->AddMacro(new AliEveMacro(AliEveMacro::kRunLoader, "REC Clus ITS",   "its_clusters.C++",   "its_clusters"));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kRunLoader, "REC Clus TPC",   "tpc_clusters.C++",   "tpc_clusters"));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kRunLoader, "REC Clus TRD",   "trd_clusters.C++",   "trd_clusters"));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kRunLoader, "REC Clus TOF",   "tof_clusters.C++",   "tof_clusters"));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kRunLoader, "REC Clus HMPID", "hmpid_clusters.C++", "hmpid_clusters"));

  exec->AddMacro(new AliEveMacro(AliEveMacro::kRunLoader, "REC Clus TOF",   "emcal_digits.C++",   "emcal_digits"));

  exec->AddMacro(new AliEveMacro(AliEveMacro::kRawReader, "RAW ITS",     "its_raw.C",     "its_raw"));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kRawReader, "RAW TPC",     "tpc_raw.C",     "tpc_raw"));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kRawReader, "RAW TOF",     "tof_raw.C",     "tof_raw"));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kRawReader, "RAW VZERO",   "vzero_raw.C",   "vzero_raw"));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kRawReader, "RAW ACORDE",  "acorde_raw.C",  "acorde_raw"));

  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC Track", "esd_tracks.C", "esd_tracks",             "", kFALSE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC Track", "esd_tracks.C", "esd_tracks_MI",          "", kFALSE));
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC Track", "esd_tracks.C", "esd_tracks_by_category", "", kTRUE));

  // ???
  exec->AddMacro(new AliEveMacro(AliEveMacro::kESD, "REC TRD", "trd_detectors.C++", "trd_detectors",         "", kFALSE));
  // trd_tracks disabled due to memory leaks

  //----------------------------------------------------------------------------

  slot = TEveWindow::CreateWindowInTab(browser->GetTabRight());
  slot->StartEmbedding();
  AliEveMacroExecutorWindow* exewin = new AliEveMacroExecutorWindow(exec);
  slot->StopEmbedding("DataSelection");
  exewin->PopulateMacros();

  //============================================================================
  // Final GUI setup
  //============================================================================

  browser->GetTabRight()->SetTab(1);

  browser->StartEmbedding(TRootBrowser::kBottom);
  new AliEveEventManagerWindow(AliEveEventManager::GetMaster());
  browser->StopEmbedding("EventCtrl");

  browser->MoveResize(0, 0, gClient->GetDisplayWidth(),
		      gClient->GetDisplayHeight() - 32);

  gEve->GetViewers()->SwitchColorSet();

  TString autoRun(gSystem->Getenv("ONLINERECO_AUTORUN"));
  if (autoRun == "1" || autoRun.CompareTo("true", TString::kIgnoreCase) == 0)
  {
    AliEveEventManager::GetMaster()->SetAutoLoad(kTRUE);
  }

  {
    TGTab *tab = gEve->GetBrowser()->GetTab(2);

    TGHorizontalFrame *hf = (TGHorizontalFrame*) tab->GetParent();
    TGVerticalFrame   *vf = (TGVerticalFrame*)   hf ->GetParent();

    hf->Resize(hf->GetWidth(), hf->GetHeight() + 80);
    vf->Layout();
  }

  gEve->FullRedraw3D(kTRUE);

  TGLViewer *glv = gMultiView->f3DView->GetGLViewer();
  glv->CurrentCamera().RotateRad(-0.4, 1);
  glv->DoDraw();
}

Int_t      g_pic_id  = 0;
Int_t      g_pic_max = 10;
TTimeStamp g_pic_prev(0, 0);

void alieve_online_on_new_event()
{
  AliESDEvent* esd = AliEveEventManager::AssertESD();
  Double_t x[3];
  esd->GetPrimaryVertex()->GetXYZ(x);

  TEveElement* top = gEve->GetCurrentEvent();

  gMultiView->DestroyEventRPhi();
  if (gCenterProjectionsAtPrimaryVertex)
    gMultiView->SetCenterRPhi(x[0], x[1], x[2]);
  gMultiView->ImportEventRPhi(top);

  gMultiView->DestroyEventRhoZ();
  if (gCenterProjectionsAtPrimaryVertex)
    gMultiView->SetCenterRhoZ(x[0], x[1], x[2]);
  gMultiView->ImportEventRhoZ(top);

  // Register image to amore.
  const TString pichost("aldaqacrs3");
  TTimeStamp now;
  Double_t delta = now.AsDouble() - g_pic_prev.AsDouble();

  printf("Pre image dump: host='%s', delta=%f.\n",
	 gSystem->HostName(), delta);

  if (pichost == gSystem->HostName() && delta >= 30)
  {
    TString id;      id.Form("online-viz-%03d", g_pic_id);
    TString pic(id); pic += ".png";

    printf("In image dump: file='%s'.\n", pic.Data());

    gEve->GetBrowser()->RaiseWindow();
    gEve->FullRedraw3D();
    gSystem->ProcessEvents();

    Int_t status;

    status = gSystem->Exec(TString::Format("xwd -id %u | convert - %s",
			   gEve->GetBrowser()->GetId(), pic.Data()));

    printf("Post capture -- status=%d.\n", status);

    status = gSystem->Exec(TString::Format("SendImageToAmore %s %s %d",
		          id.Data(), pic.Data(),
		          AliEveEventManager::AssertRawReader()->GetRunNumber()));

    printf("Post AMORE reg -- status=%d, run=%d.\n", status,
	   AliEveEventManager::AssertRawReader()->GetRunNumber());

    if (++g_pic_id >= g_pic_max)
      g_pic_id = 0;
    g_pic_prev.Set();
  }
}
<|endoftext|>


<commit_before>/*
**
** Author(s):
**  - Julien Freche <jfreche@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#ifndef QI_PYTHON_SIGNAL_HPP_
# define QI_PYTHON_SIGNAL_HPP_

# include <qitype/signal.hpp>

// If included first doesn't compile with clang on OSX
# include <Python.h>

class qi_signal
{
  public:
    qi_signal();
    ~qi_signal();

    unsigned int connect(PyObject* callback);
    bool disconnect(unsigned int);
    bool disconnectAll();

    void trigger(PyObject* arg0 = NULL,
                 PyObject* arg1 = NULL,
                 PyObject* arg2 = NULL,
                 PyObject* arg3 = NULL,
                 PyObject* arg4 = NULL,
                 PyObject* arg5 = NULL,
                 PyObject* arg6 = NULL,
                 PyObject* arg7 = NULL,
                 PyObject* arg8 = NULL,
                 PyObject* arg9 = NULL);

  private:
    void callback(PyObject* callback, const std::vector<PyObject*>& args);

    std::map<unsigned int, PyObject*>               _callbackMap;
    qi::Signal<void (std::vector<PyObject*>)>       _sig;

    class EventLoopHandler
    {
      public:
        EventLoopHandler()
          : eventLoop ()
        {
          eventLoop.start();
        }

        ~EventLoopHandler()
        {
          eventLoop.stop();
          eventLoop.join();
        }

        qi::EventLoop eventLoop;
    };

    static EventLoopHandler                         _elHandler;
};

#endif // !QI_PYTHON_SIGNAL_HPP_
<commit_msg>Python bindings : qi_signal use an eventLoop with threadpool<commit_after>/*
**
** Author(s):
**  - Julien Freche <jfreche@aldebaran-robotics.com>
**
** Copyright (C) 2012 Aldebaran Robotics
*/

#ifndef QI_PYTHON_SIGNAL_HPP_
# define QI_PYTHON_SIGNAL_HPP_

# include <qitype/signal.hpp>

// If included first doesn't compile with clang on OSX
# include <Python.h>

class qi_signal
{
  public:
    qi_signal();
    ~qi_signal();

    unsigned int connect(PyObject* callback);
    bool disconnect(unsigned int);
    bool disconnectAll();

    void trigger(PyObject* arg0 = NULL,
                 PyObject* arg1 = NULL,
                 PyObject* arg2 = NULL,
                 PyObject* arg3 = NULL,
                 PyObject* arg4 = NULL,
                 PyObject* arg5 = NULL,
                 PyObject* arg6 = NULL,
                 PyObject* arg7 = NULL,
                 PyObject* arg8 = NULL,
                 PyObject* arg9 = NULL);

  private:
    void callback(PyObject* callback, const std::vector<PyObject*>& args);

    std::map<unsigned int, PyObject*>               _callbackMap;
    qi::Signal<void (std::vector<PyObject*>)>       _sig;

    class EventLoopHandler
    {
      public:
        EventLoopHandler()
          : eventLoop ()
        {
          eventLoop.startThreadPool();
        }

        ~EventLoopHandler()
        {
          eventLoop.stop();
          eventLoop.join();
        }

        qi::EventLoop eventLoop;
    };

    static EventLoopHandler                         _elHandler;
};

#endif // !QI_PYTHON_SIGNAL_HPP_
<|endoftext|>


<commit_before>/*
Copyright (c) 2012-2014 The SSDB Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <string>
#include <vector>
#include <map>
#include "net/link.h"
#include "net/fde.h"
#include "util/log.h"
#include "util/strings.h"
#include "version.h"

#include "../src/include.h"

struct Data
{
	std::string key;
	std::string val;
	std::string num;
};

std::map<std::string, Data *> *ds;
Fdevents *fdes;
std::vector<Link *> *free_links;

std::vector<std::string> test_cases;

void welcome(){
	printf("ssdb-bench - SSDB benchmark tool, %s\n", SSDB_VERSION);
	printf("Copyright (c) 2013-2014 ssdb.io\n");
	printf("\n");
}

void usage(int argc, char **argv){
	printf("Usage:\n");
	printf("    %s [-h host] [-p port] [-n requests] [-c clients] [-s size] [-t test_cases] [-s size]\n", argv[0]);
	printf("\n");
	printf("Options:\n");
	printf("    ip          server ip (default 127.0.0.1)\n");
	printf("    port        server port (default 8888)\n");
	printf("    requests    Total number of requests (default 10000)\n");
	printf("    clients     Number of parallel connections (default 50)\n");
	printf("    size        Size of item\n");
	printf("    test_case   change the test_case to run, default is all. for example: set or set,get or set,get,hset,hget\n");
	printf("\n");
}

bool is_test_case(std::string cmd){
    if (test_cases.empty()) {
        // all case
        return true;
    }

    for(std::vector<std::string>::iterator it = test_cases.begin(); it != test_cases.end(); it ++) {
        if (*it == cmd) {
            return true;
        }
    }

    return false;
}

void init_data(int num, int size){
	srand(time(NULL));
    char buf[32];
    snprintf(buf,sizeof(buf),"%d",size);
    std::string tmp;
    tmp.append("%0");
    tmp.append(buf);
    tmp.append("d");

	ds = new std::map<std::string, Data *>();
	while(ds->size() < num){
		Data *d = new Data();
		char buf[1024];

		int n = rand();
		snprintf(buf, sizeof(buf), "%d", n);
		d->num = buf;
		snprintf(buf, sizeof(buf), "%ld", ds->size());
		d->key = buf;
		snprintf(buf, sizeof(buf), tmp.c_str(), n);
		d->val = buf;
		ds->insert(make_pair(d->num, d));
	}
}

void init_links(int num, const char *ip, int port){
	fdes = new Fdevents();
	free_links = new std::vector<Link *>();

	for(int i=0; i<num; i++){
		Link *link = Link::connect(ip, port);
		if(!link){
			fprintf(stderr, "connect error! %s\n", strerror(errno));
			exit(0);
		}
		fdes->set(link->fd(), FDEVENT_IN, 0, link);
		free_links->push_back(link);
	}
}

void send_req(Link *link, const std::string &cmd, const Data *d){
	if(cmd == "set"){
		link->send(cmd, d->key, d->val);
	}else if(cmd == "get"){
		link->send(cmd, d->key);
	}else if(cmd == "del"){
		link->send(cmd, d->key);
	}else if(cmd == "hset"){
		link->send(cmd, "TEST", d->key, d->val);
	}else if(cmd == "hget"){
		link->send(cmd, "TEST", d->key);
	}else if(cmd == "hdel"){
		link->send(cmd, "TEST", d->key);
	}else if(cmd == "zset"){
		link->send(cmd, "TEST", d->key, d->num);
	}else if(cmd == "zget"){
		link->send(cmd, "TEST", d->key);
	}else if(cmd == "zdel"){
		link->send(cmd, "TEST", d->key);
	}else if(cmd == "qpush"){
		link->send(cmd, "TEST", d->key);
	}else if(cmd == "qpop"){
		link->send(cmd, "TEST");
	}else{
		log_error("bad command!");
		exit(0);
	}
	link->flush();
}

void bench(std::string cmd){
	if (!is_test_case(cmd)) {
		return;
	}

	int total = (int)ds->size();
	int finished = 0;
	int num_sent = 0;

	printf("========== %s ==========\n", cmd.c_str());

	std::map<std::string, Data *>::iterator it;
	it = ds->begin();

	double stime = millitime();
	while(1){
		while(!free_links->empty()){
			if(num_sent == total){
				break;
			}
			num_sent ++;

			Link *link = free_links->back();
			free_links->pop_back();

			send_req(link, cmd, it->second);
			it ++;
		}

		const Fdevents::events_t *events;
		events = fdes->wait(50);
		if(events == NULL){
			log_error("events.wait error: %s", strerror(errno));
			break;
		}

		for(int i=0; i<(int)events->size(); i++){
			const Fdevent *fde = events->at(i);
			Link *link = (Link *)fde->data.ptr;

			int len = link->read();
			if(len <= 0){
				log_error("fd: %d, read: %d, delete link", link->fd(), len);
				exit(0);
			}

			const std::vector<Bytes> *resp = link->recv();
			if(resp == NULL){
				log_error("error");
				break;
			}else if(resp->empty()){
				continue;
			}else{
				if(resp->at(0) != "ok"){
					log_error("bad response: %s", resp->at(0).String().c_str());
					exit(0);
				}
				free_links->push_back(link);
				finished ++;
				if(finished == total){
					double etime = millitime();
					double ts = (stime == etime)? 1 : (etime - stime);
					double speed = total / ts;
					printf("qps: %d, time: %.3f s\n", (int)speed, ts);
					return;
				}
			}
		}
	}
}

int main(int argc, char **argv){
	const char *ip = "127.0.0.1";
	int port = 8888;
	int requests = 10000;
	int clients = 50;
	int size = 100;

	welcome();
	usage(argc, argv);

	if((argc - 1) % 2 != 0) {
	    printf("Param error***************************\n");
        exit(0);
    }

	for(int i=1; i<argc; i++){
		if(strcmp("-v", argv[i]) == 0){
			exit(0);
		} else if(strcmp("-p", argv[i]) == 0) {
            port = atoi(argv[++i]);
        } else if(strcmp("-h", argv[i]) == 0) {
            ip = argv[++i];
        } else if(strcmp("-c", argv[i]) == 0) {
            clients = atoi(argv[++i]);
        } else if(strcmp("-n", argv[i]) == 0) {
            requests = atoi(argv[++i]);
        } else if(strcmp("-n", argv[i]) == 0) {
            size = atoi(argv[++i]);
        } else if(strcmp("-t", argv[i]) == 0) {
            str_split(argv[++i], test_cases, ",");
        } else {
	        printf("Param error***************************\n");
            exit(0);
        }
	}

	//printf("preparing data...\n");
	init_data(requests, size);
	//printf("preparing links...\n");
	init_links(clients, ip, port);

	bench("set");
	bench("get");
	bench("del");

	bench("hset");
	bench("hget");
	bench("hdel");

	bench("zset");
	bench("zget");
	bench("zdel");

	bench("qpush");
	bench("qpop");

	printf("\n");

	return 0;
}

<commit_msg>调整ssdb-bench.cpp，fix -s 参数的问题<commit_after>/*
Copyright (c) 2012-2014 The SSDB Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <errno.h>
#include <string>
#include <vector>
#include <map>
#include "net/link.h"
#include "net/fde.h"
#include "util/log.h"
#include "util/strings.h"
#include "version.h"

#include "../src/include.h"

struct Data
{
	std::string key;
	std::string val;
	std::string num;
};

std::map<std::string, Data *> *ds;
Fdevents *fdes;
std::vector<Link *> *free_links;

std::vector<std::string> test_cases;

void welcome(){
	printf("ssdb-bench - SSDB benchmark tool, %s\n", SSDB_VERSION);
	printf("Copyright (c) 2013-2014 ssdb.io\n");
	printf("\n");
}

void usage(int argc, char **argv){
	printf("Usage:\n");
	printf("    %s [-h host] [-p port] [-n requests] [-c clients] [-s size] [-t test_cases] [-s size]\n", argv[0]);
	printf("\n");
	printf("Options:\n");
	printf("    ip          server ip (default 127.0.0.1)\n");
	printf("    port        server port (default 8888)\n");
	printf("    requests    Total number of requests (default 10000)\n");
	printf("    clients     Number of parallel connections (default 50)\n");
	printf("    size        Size of item\n");
	printf("    test_case   change the test_case to run, default is all. for example: set or set,get or set,get,hset,hget\n");
	printf("\n");
}

bool is_test_case(std::string cmd){
    if (test_cases.empty()) {
        // all case
        return true;
    }

    for(std::vector<std::string>::iterator it = test_cases.begin(); it != test_cases.end(); it ++) {
        if (*it == cmd) {
            return true;
        }
    }

    return false;
}

void init_data(int num, int size){
	srand(time(NULL));
    char buf[32];
    snprintf(buf,sizeof(buf),"%d",size);
    std::string tmp;
    tmp.append("%0");
    tmp.append(buf);
    tmp.append("d");

	ds = new std::map<std::string, Data *>();
	while(ds->size() < num){
		Data *d = new Data();
		char buf[1024];

		int n = rand();
		snprintf(buf, sizeof(buf), "%d", n);
		d->num = buf;
		snprintf(buf, sizeof(buf), "%ld", ds->size());
		d->key = buf;
		snprintf(buf, sizeof(buf), tmp.c_str(), n);
		d->val = buf;
		ds->insert(make_pair(d->num, d));
	}
}

void init_links(int num, const char *ip, int port){
	fdes = new Fdevents();
	free_links = new std::vector<Link *>();

	for(int i=0; i<num; i++){
		Link *link = Link::connect(ip, port);
		if(!link){
			fprintf(stderr, "connect error! %s\n", strerror(errno));
			exit(0);
		}
		fdes->set(link->fd(), FDEVENT_IN, 0, link);
		free_links->push_back(link);
	}
}

void send_req(Link *link, const std::string &cmd, const Data *d){
	if(cmd == "set"){
		link->send(cmd, d->key, d->val);
	}else if(cmd == "get"){
		link->send(cmd, d->key);
	}else if(cmd == "del"){
		link->send(cmd, d->key);
	}else if(cmd == "hset"){
		link->send(cmd, "TEST", d->key, d->val);
	}else if(cmd == "hget"){
		link->send(cmd, "TEST", d->key);
	}else if(cmd == "hdel"){
		link->send(cmd, "TEST", d->key);
	}else if(cmd == "zset"){
		link->send(cmd, "TEST", d->key, d->num);
	}else if(cmd == "zget"){
		link->send(cmd, "TEST", d->key);
	}else if(cmd == "zdel"){
		link->send(cmd, "TEST", d->key);
	}else if(cmd == "qpush"){
		link->send(cmd, "TEST", d->key);
	}else if(cmd == "qpop"){
		link->send(cmd, "TEST");
	}else{
		log_error("bad command!");
		exit(0);
	}
	link->flush();
}

void bench(std::string cmd){
	if (!is_test_case(cmd)) {
		return;
	}

	int total = (int)ds->size();
	int finished = 0;
	int num_sent = 0;

	printf("========== %s ==========\n", cmd.c_str());

	std::map<std::string, Data *>::iterator it;
	it = ds->begin();

	double stime = millitime();
	while(1){
		while(!free_links->empty()){
			if(num_sent == total){
				break;
			}
			num_sent ++;

			Link *link = free_links->back();
			free_links->pop_back();

			send_req(link, cmd, it->second);
			it ++;
		}

		const Fdevents::events_t *events;
		events = fdes->wait(50);
		if(events == NULL){
			log_error("events.wait error: %s", strerror(errno));
			break;
		}

		for(int i=0; i<(int)events->size(); i++){
			const Fdevent *fde = events->at(i);
			Link *link = (Link *)fde->data.ptr;

			int len = link->read();
			if(len <= 0){
				log_error("fd: %d, read: %d, delete link", link->fd(), len);
				exit(0);
			}

			const std::vector<Bytes> *resp = link->recv();
			if(resp == NULL){
				log_error("error");
				break;
			}else if(resp->empty()){
				continue;
			}else{
				if(resp->at(0) != "ok"){
					log_error("bad response: %s", resp->at(0).String().c_str());
					exit(0);
				}
				free_links->push_back(link);
				finished ++;
				if(finished == total){
					double etime = millitime();
					double ts = (stime == etime)? 1 : (etime - stime);
					double speed = total / ts;
					printf("qps: %d, time: %.3f s\n", (int)speed, ts);
					return;
				}
			}
		}
	}
}

int main(int argc, char **argv){
	const char *ip = "127.0.0.1";
	int port = 8888;
	int requests = 10000;
	int clients = 50;
	int size = 100;

	welcome();
	usage(argc, argv);

	if((argc - 1) % 2 != 0) {
	    printf("Param error***************************\n");
        exit(0);
    }

	for(int i=1; i<argc; i++){
		if(strcmp("-v", argv[i]) == 0){
			exit(0);
		} else if(strcmp("-p", argv[i]) == 0) {
            port = atoi(argv[++i]);
        } else if(strcmp("-h", argv[i]) == 0) {
            ip = argv[++i];
        } else if(strcmp("-c", argv[i]) == 0) {
            clients = atoi(argv[++i]);
        } else if(strcmp("-n", argv[i]) == 0) {
            requests = atoi(argv[++i]);
        } else if(strcmp("-s", argv[i]) == 0) {
            size = atoi(argv[++i]);
        } else if(strcmp("-t", argv[i]) == 0) {
            str_split(argv[++i], test_cases, ",");
        } else {
	        printf("Param error***************************\n");
            exit(0);
        }
	}

	//printf("preparing data...\n");
	init_data(requests, size);
	//printf("preparing links...\n");
	init_links(clients, ip, port);

	bench("set");
	bench("get");
	bench("del");

	bench("hset");
	bench("hget");
	bench("hdel");

	bench("zset");
	bench("zget");
	bench("zdel");

	bench("qpush");
	bench("qpop");

	printf("\n");

	return 0;
}

<|endoftext|>


<commit_before>#include <iostream>
#include <vector>

using namespace std;

//  min queue, index 1 is the top
//  0 1 2 3 4 5 6
//
// a min queue
class PQ {
public:
    PQ() {
        // 0 is not used
        v.resize(1);
    }

    PQ(const int* A, int n) {
        v.resize(n+1);
    }

    int top() {
        return v[1];
    }

    void push(int x) {
        // bottom-up, swim up v.back
        v.push_back(x);
        int i = v.size() -1;
        int j;
        while(i > 1) {
            j = i/2;
            // current v[i] less then parent v[j], swap
            if(v[i] < v[j]) {
                swap(v[i], v[j]);
            } else {
                break;
            }
            i = j;
        }
    }

    void pop() {
        // top down, swap root and v.back, then sink root
        swap(v[1], v.back());
        v.pop_back();
        int i = 1;
        int j;
        // if current v[i] has no left child, then nonthing to do
        while(i*2 < v.size()) {
            // left child
            j = i * 2;
            // try right child if right child is smaller
            if(j + 1 < v.size() && v[j+1] < v[j]) j++;
            // swap if root v[i] is bigger than the smaller child v[j], else done
            if(v[i] > v[j]) {
                swap(v[i], v[j]);
            } else {
                break;
            }
            i = j;
        }
    }

    bool empty() {
        return size() == 0;
    }

    int size() {
        return v.size() - 1;
    }
private:
    // the last is top
    vector<int> v;
};

int main() {

    vector<int> v = {10, 2, 3, 5, 8, 2, 2, -1, 100, 89};

    PQ q;
    for(auto x: v) {
        q.push(x);
    }
    while(! q.empty()) {
        cout << q.top() << endl;
        q.pop();
    }
    return 0;
}
<commit_msg>add construct pq<commit_after>#include <iostream>
#include <vector>

using namespace std;

//  min queue, index 1 is the top
//  0 1 2 3 4 5 6
//
// a min queue
class PQ {
public:
    PQ() {
        // 0 is not used
        v.resize(1);
    }

    // build heap in bottom up order, sink nodes from n/2 to 1
    // and it takes O(N)
    PQ(const int* A, int n) {
        v.resize(n+1);
        for(int i = 0; i < n; i++) {
            v[i+1] = A[i];
        }
        int k = n / 2, i, j;
        while(k >= 1) {
            i = k;
            while(i * 2 <= n) {
                j = i * 2;
                if(j + 1 <= n && v[j+1] < v[j]) j++;
                if(v[j] < v[i]) swap(v[i], v[j]);
                i = j;
            }
            k--;
        }
    }

    int top() {
        return v[1];
    }

    void push(int x) {
        // bottom-up, swim up v.back
        v.push_back(x);
        int i = v.size() -1;
        int j;
        while(i > 1) {
            j = i/2;
            // current v[i] less then parent v[j], swap
            if(v[i] < v[j]) {
                swap(v[i], v[j]);
            } else {
                break;
            }
            i = j;
        }
    }

    void pop() {
        // top down, swap root and v.back, then sink root
        swap(v[1], v.back());
        v.pop_back();
        int i = 1;
        int j;
        // if current v[i] has no left child, then nonthing to do
        while(i*2 < v.size()) {
            // left child
            j = i * 2;
            // try right child if right child is smaller
            if(j + 1 < v.size() && v[j+1] < v[j]) j++;
            // swap if root v[i] is bigger than the smaller child v[j], else done
            if(v[i] > v[j]) {
                swap(v[i], v[j]);
            } else {
                break;
            }
            i = j;
        }
    }

    bool empty() {
        return size() == 0;
    }

    int size() {
        return v.size() - 1;
    }
private:
    // the last is top
    vector<int> v;
};

int main() {

    vector<int> v = {10, 2, 3, 5, 8, 2, 2, -1, 100, 89};

    PQ q;
    for(auto x: v) {
        q.push(x);
    }
    while(! q.empty()) {
        cout << q.top() << " ";
        q.pop();
    }
    cout << endl;

    PQ q1(v.data(), v.size());
    while(! q1.empty()) {
        cout << q1.top() << " ";
        q1.pop();
    }
    cout << endl;

    return 0;
}
<|endoftext|>