<commit_before>/** @file */

#pragma once

#include "caney/std/tags.hpp"

#include "internal.hpp"

#include <cstring>
#include <memory>

#include <boost/noncopyable.hpp>
#include <boost/smart_ptr/intrusive_ptr.hpp>
/* counter policies: */
#include <boost/smart_ptr/intrusive_ref_counter.hpp>

__CANEY_MEMORYV1_BEGIN

template <typename Object, typename CounterPolicyT = boost::thread_safe_counter, typename Allocator = std::allocator<void>>
class intrusive_base;

namespace impl {
	/* wrap allocator to allow "late" construction; that
	 * the allocator doesn't need to go through all constructors
	 */
	template <typename Allocator>
	class intrusive_allocator {
	private:
		union inner {
			inner() {}
			inner(inner const&) = delete;
			~inner() {}
			Allocator m_allocator;
		};
		inner m_inner;

	public:
		void init_allocator(Allocator const& alloc) noexcept {
			new (&m_inner.m_allocator) Allocator(alloc);
		}

		void clear_allocator() noexcept {
			m_inner.m_allocator.~Allocator();
		}

		Allocator& allocator() noexcept {
			return m_inner.m_allocator;
		}
	};

	/* wrap counter to prevent copying */
	template <typename CounterPolicyT>
	class intrusive_counter {
	private:
		using counter_type = typename CounterPolicyT::type;
		counter_type m_counter{0};

	public:
		intrusive_counter() noexcept {}
		intrusive_counter(intrusive_counter const&) = delete;
		~intrusive_counter() = default;

		auto load() const noexcept -> decltype(CounterPolicyT::load(m_counter)) {
			return CounterPolicyT::load(m_counter);
		}

		void increment() noexcept {
			CounterPolicyT::increment(m_counter);
		}

		auto decrement() noexcept -> decltype(CounterPolicyT::decrement(m_counter)) {
			return CounterPolicyT::decrement(m_counter);
		}
	};

	// actual traits type
	template <typename Object, typename CounterPolicyT, typename Allocator>
	struct intrusive_traits_impl {
		using object_t = Object;
		using counter_policy_t = CounterPolicyT;
		using allocator_t = Allocator;
		using base_t = intrusive_base<Object, CounterPolicyT, Allocator>;

		template <typename Derived>
		static void add_ref(Derived* p) noexcept;

		template <typename Derived>
		static void release(Derived* p) noexcept;

		template <typename Derived>
		static void init_allocator(Derived* p, Allocator const& alloc) noexcept;
	};

	// if `Base` is a `intrusive_base`, `::type` type member will be `intrusive_traits_impl`
	template <typename Base>
	struct intrusive_traits_base {};

	template <typename Object, typename CounterPolicyT, typename Allocator>
	struct intrusive_traits_base<intrusive_base<Object, CounterPolicyT, Allocator>> {
		using type = intrusive_traits_impl<Object, CounterPolicyT, Allocator>;
	};

	// detect a `intrusive_base<...>` base type of `Derived`
	template <typename Derived>
	struct intrusive_traits_detect {
	private:
		template <typename T, typename Object, typename CounterPolicyT, typename Allocator>
		static intrusive_base<Object, CounterPolicyT, Allocator> test(intrusive_base<Object, CounterPolicyT, Allocator> const*);
		template <typename T>
		static void test(void const*, T* = nullptr);

	public:
		// `void` or the `intrusive_base<...>` base type of `Derived`
		using base = decltype(test<Derived>((Derived*) nullptr));
		// `type` will have a `::type` type member if `base` is not `void`
		using type = intrusive_traits_base<base>;
	};

	// get traits for a `Derived` type (must be derived from `intrusive_base<...>` or this fails)
	template <typename Derived>
	using intrusive_traits = typename intrusive_traits_detect<Derived>::type::type;
} // namespace impl

/**
 * @brief similar to `boost::intrusive_ref_counter` this is a base class to derive
 * from if you want to manager your objects with `boost::intrusive_ptr`, but supports
 * custom allocators.
 *
 * @tparam Object         the object deriving from this class. if you want to derive from Object
 *                        as well, Object needs a virtual destructor
 * @tparam CounterPolicyT same as CounterPolicyT `boost::intrusive_ref_counter`
 * @tparam Allocator      allocator to allocate and deallocate objects with
 */
template <typename Object, typename CounterPolicyT /* = boost::thread_safe_counter */, typename Allocator /* = std::allocator<void> */>
class intrusive_base {
private:
	mutable impl::intrusive_counter<CounterPolicyT> m_counter;
	mutable impl::intrusive_allocator<Allocator> m_allocator;

	friend struct impl::intrusive_traits_impl<Object, CounterPolicyT, Allocator>;

protected:
	/**
	 * @brief allocator used to allocate this object. not valid during construction.
	 */
	Allocator const& allocator() const {
		return m_allocator.allocator();
	}

public:
	/**
	 * @brief how many pointers reference the object
	 */
	auto use_count() const -> decltype(m_counter.load()) {
		return m_counter.load();
	}

	/**
	 * @brief whether there is exactly one reference
	 */
	bool unique() const {
		return 1 == m_counter.load();
	}

	/**
	 * @brief shortcut for @ref allocate_intrusive(), but only allocates
	 * objects of types derived from `Object`.
	 *
	 * Creates objects of type `Object` by default, even when called through
	 * a derived class like `Derived::allocate` - call `Derived::allocate<Derived>`
	 * or `Object::allocate<Derived>` instead.
	 */
	template <typename Derived = Object, typename... Args>
	static boost::intrusive_ptr<Derived> allocate(Allocator const& alloc, Args&&... args);

	/**
	 * @brief shortcut for @ref make_intrusive(), but only creates
	 * objects of types derived from `Object`.
	 *
	 * Creates objects of type `Object` by default, even when called through
	 * a derived class like `Derived::allocate` - call `Derived::create<Derived>`
	 * or `Object::create<Derived>` instead.
	 */
	template <typename Derived = Object, typename... Args>
	static boost::intrusive_ptr<Derived> create(Args&&... args);
};

template <typename Object, typename CounterPolicyT, typename Allocator>
template <typename Derived>
/* static */
void impl::intrusive_traits_impl<Object, CounterPolicyT, Allocator>::add_ref(Derived* p) noexcept {
	p->base_t::m_counter.increment();
}

template <typename Object, typename CounterPolicyT, typename Allocator>
template <typename Derived>
/* static */
void impl::intrusive_traits_impl<Object, CounterPolicyT, Allocator>::release(Derived* p) noexcept {
	if (0 == p->base_t::m_counter.decrement()) {
		using derived_no_cv = typename std::remove_cv<Derived>::type;

		static_assert(
			std::is_same<derived_no_cv, object_t>::value || std::has_virtual_destructor<object_t>::value,
			"Can only derive from Object if it has a virtual destructor");

		using derived_alloc_t = typename std::allocator_traits<allocator_t>::template rebind_alloc<derived_no_cv>;
		using derived_alloc_traits = std::allocator_traits<derived_alloc_t>;
		derived_alloc_t derived_alloc(p->base_t::m_allocator.allocator());
		derived_no_cv* ptr = const_cast<derived_no_cv*>(p);

		p->base_t::m_allocator.clear_allocator();
		derived_alloc_traits::destroy(derived_alloc, ptr);
		derived_alloc_traits::deallocate(derived_alloc, ptr, 1);
	}
}

template <typename Object, typename CounterPolicyT, typename Allocator>
template <typename Derived>
/* static */
void impl::intrusive_traits_impl<Object, CounterPolicyT, Allocator>::init_allocator(Derived* p, Allocator const& alloc) noexcept {
	p->base_t::m_allocator.init_allocator(alloc);
}

/**
 * @brief helper function for boost::intrusive_ptr reference counter management
 * @internal
 */
template <typename Derived, typename traits = impl::intrusive_traits<Derived>>
void intrusive_ptr_add_ref(Derived* p) noexcept {
	traits::add_ref(p);
}

/**
 * @brief helper function for boost::intrusive_ptr reference counter management
 * @internal
 */
template <typename Derived, typename traits = impl::intrusive_traits<Derived>>
void intrusive_ptr_release(Derived* p) noexcept {
	traits::release(p);
}

/**
 * allocate object of type `Derived` (which must derive from @ref intrusive_base) and
 * return a `boost::intrusive_ptr` to it.
 * @param alloc    Allocator to allocate object with
 * @param args     Arguments to pass to `Derived` constructor
 * @tparam Derived type of object to create
 */
template <typename Derived, typename traits = impl::intrusive_traits<Derived>, typename... Args>
boost::intrusive_ptr<Derived> allocate_intrusive(typename traits::allocator_t const& alloc, Args&&... args) {
	using alloc_t = typename traits::allocator_t;
	using derived_alloc_t = typename std::allocator_traits<alloc_t>::template rebind_alloc<Derived>;
	using derived_alloc_traits = std::allocator_traits<derived_alloc_t>;
	derived_alloc_t derived_alloc(alloc);

	typename derived_alloc_traits::pointer ptr = derived_alloc_traits::allocate(derived_alloc, 1);
	typename traits::base_t* base_ptr = ptr;
	try {
		derived_alloc_traits::construct(derived_alloc, ptr, std::forward<Args>(args)...);
		traits::init_allocator(base_ptr, alloc);
	} catch (...) {
		derived_alloc_traits::deallocate(derived_alloc, ptr, 1);
		throw;
	}

	return boost::intrusive_ptr<Derived>(ptr);
}

/**
 * @brief create a new object of type `Derived` which must derive from @ref intrusive_base)
 * using a default constructed allocator.
 * @param args     Arguments to forward to contructor of `Derived`
 * @tparam Derived type of object to create
 */
template <typename Derived, typename traits = impl::intrusive_traits<Derived>, typename... Args>
boost::intrusive_ptr<Derived> make_intrusive(Args&&... args) {
	using alloc_t = typename traits::allocator_t;
	return allocate_intrusive<Derived>(alloc_t(), std::forward<Args>(args)...);
}

template <typename Object, typename CounterPolicyT, typename Allocator>
template <typename Derived, typename... Args>
/* static */
boost::intrusive_ptr<Derived> intrusive_base<Object, CounterPolicyT, Allocator>::allocate(Allocator const& alloc, Args&&... args) {
	static_assert(std::is_base_of<Object, Derived>::value, "only create derived objects");
	return allocate_intrusive<Derived>(alloc, std::forward<Args>(args)...);
}

template <typename Object, typename CounterPolicyT, typename Allocator>
template <typename Derived, typename... Args>
/* static */
boost::intrusive_ptr<Derived> intrusive_base<Object, CounterPolicyT, Allocator>::create(Args&&... args) {
	static_assert(std::is_base_of<Object, Derived>::value, "only create derived objects");
	return make_intrusive<Derived>(std::forward<Args>(args)...);
}

__CANEY_MEMORYV1_END
<commit_msg>[memory] fix issues with conflicting private typename<commit_after>/** @file */

#pragma once

#include "caney/std/tags.hpp"

#include "internal.hpp"

#include <cstring>
#include <memory>

#include <boost/noncopyable.hpp>
#include <boost/smart_ptr/intrusive_ptr.hpp>
/* counter policies: */
#include <boost/smart_ptr/intrusive_ref_counter.hpp>

__CANEY_MEMORYV1_BEGIN

template <typename Object, typename CounterPolicyT = boost::thread_safe_counter, typename Allocator = std::allocator<void>>
class intrusive_base;

namespace impl {
	/* wrap allocator to allow "late" construction; that
	 * the allocator doesn't need to go through all constructors
	 */
	template <typename Allocator>
	class intrusive_allocator {
	private:
		union inner {
			inner() {}
			inner(inner const&) = delete;
			~inner() {}
			Allocator m_allocator;
		};
		inner m_inner;

	public:
		void init_allocator(Allocator const& alloc) noexcept {
			new (&m_inner.m_allocator) Allocator(alloc);
		}

		void clear_allocator() noexcept {
			m_inner.m_allocator.~Allocator();
		}

		Allocator& allocator() noexcept {
			return m_inner.m_allocator;
		}
	};

	/* wrap counter to prevent copying */
	template <typename CounterPolicyT>
	class intrusive_counter {
	private:
		using counter_type = typename CounterPolicyT::type;
		counter_type m_counter{0};

	public:
		intrusive_counter() noexcept {}
		intrusive_counter(intrusive_counter const&) = delete;
		~intrusive_counter() = default;

		auto load() const noexcept -> decltype(CounterPolicyT::load(m_counter)) {
			return CounterPolicyT::load(m_counter);
		}

		void increment() noexcept {
			CounterPolicyT::increment(m_counter);
		}

		auto decrement() noexcept -> decltype(CounterPolicyT::decrement(m_counter)) {
			return CounterPolicyT::decrement(m_counter);
		}
	};

	// actual traits type
	template <typename Object, typename CounterPolicyT, typename Allocator>
	struct intrusive_traits_impl {
		using object_t = Object;
		using counter_policy_t = CounterPolicyT;
		using allocator_t = Allocator;
		using base_t = intrusive_base<Object, CounterPolicyT, Allocator>;

		template <typename Derived>
		static void add_ref(Derived* p) noexcept;

		template <typename Derived>
		static void release(Derived* p) noexcept;

		template <typename Derived>
		static void init_allocator(Derived* p, Allocator const& alloc) noexcept;
	};

	// if `Base` is a `intrusive_base`, `::type` type member will be `intrusive_traits_impl`
	template <typename Base>
	struct intrusive_traits_base {};

	template <typename Object, typename CounterPolicyT, typename Allocator>
	struct intrusive_traits_base<intrusive_base<Object, CounterPolicyT, Allocator>> {
		using type = intrusive_traits_impl<Object, CounterPolicyT, Allocator>;
	};

	// detect a `intrusive_base<...>` base type of `Derived`
	template <typename Derived>
	struct intrusive_traits_detect {
	private:
		template <typename T, typename Object, typename CounterPolicyT, typename Allocator>
		static intrusive_base<Object, CounterPolicyT, Allocator> test(intrusive_base<Object, CounterPolicyT, Allocator> const*);
		template <typename T>
		static void test(void const*, T* = nullptr);

	public:
		// `void` or the `intrusive_base<...>` base type of `Derived`
		using base = decltype(test<Derived>((Derived*) nullptr));
		// `type` will have a `::type` type member if `base` is not `void`
		using type = intrusive_traits_base<base>;
	};

	// get traits for a `Derived` type (must be derived from `intrusive_base<...>` or this fails)
	template <typename Derived>
	using intrusive_traits = typename intrusive_traits_detect<Derived>::type::type;
} // namespace impl

/**
 * @brief similar to `boost::intrusive_ref_counter` this is a base class to derive
 * from if you want to manager your objects with `boost::intrusive_ptr`, but supports
 * custom allocators.
 *
 * @tparam Object         the object deriving from this class. if you want to derive from Object
 *                        as well, Object needs a virtual destructor
 * @tparam CounterPolicyT same as CounterPolicyT `boost::intrusive_ref_counter`
 * @tparam Allocator      allocator to allocate and deallocate objects with
 */
template <typename Object, typename CounterPolicyT /* = boost::thread_safe_counter */, typename Allocator /* = std::allocator<void> */>
class intrusive_base {
private:
	mutable impl::intrusive_counter<CounterPolicyT> m_counter;
	mutable impl::intrusive_allocator<Allocator> m_allocator;

	friend struct impl::intrusive_traits_impl<Object, CounterPolicyT, Allocator>;

protected:
	/**
	 * @brief allocator used to allocate this object. not valid during construction.
	 */
	Allocator const& allocator() const {
		return m_allocator.allocator();
	}

public:
	/**
	 * @brief how many pointers reference the object
	 */
	auto use_count() const -> decltype(m_counter.load()) {
		return m_counter.load();
	}

	/**
	 * @brief whether there is exactly one reference
	 */
	bool unique() const {
		return 1 == m_counter.load();
	}

	/**
	 * @brief shortcut for @ref allocate_intrusive(), but only allocates
	 * objects of types derived from `Object`.
	 *
	 * Creates objects of type `Object` by default, even when called through
	 * a derived class like `Derived::allocate` - call `Derived::allocate<Derived>`
	 * or `Object::allocate<Derived>` instead.
	 */
	template <typename Derived = Object, typename... Args>
	static boost::intrusive_ptr<Derived> allocate(Allocator const& alloc, Args&&... args);

	/**
	 * @brief shortcut for @ref make_intrusive(), but only creates
	 * objects of types derived from `Object`.
	 *
	 * Creates objects of type `Object` by default, even when called through
	 * a derived class like `Derived::allocate` - call `Derived::create<Derived>`
	 * or `Object::create<Derived>` instead.
	 */
	template <typename Derived = Object, typename... Args>
	static boost::intrusive_ptr<Derived> create(Args&&... args);
};

template <typename Object, typename CounterPolicyT, typename Allocator>
template <typename Derived>
/* static */
void impl::intrusive_traits_impl<Object, CounterPolicyT, Allocator>::add_ref(Derived* p) noexcept {
	base_t const* const b = p;
	b->m_counter.increment();
}

template <typename Object, typename CounterPolicyT, typename Allocator>
template <typename Derived>
/* static */
void impl::intrusive_traits_impl<Object, CounterPolicyT, Allocator>::release(Derived* p) noexcept {
	base_t const* const b = p;
	if (0 == b->m_counter.decrement()) {
		using derived_no_cv = typename std::remove_cv<Derived>::type;

		static_assert(
			std::is_same<derived_no_cv, object_t>::value || std::has_virtual_destructor<object_t>::value,
			"Can only derive from Object if it has a virtual destructor");

		using derived_alloc_t = typename std::allocator_traits<allocator_t>::template rebind_alloc<derived_no_cv>;
		using derived_alloc_traits = std::allocator_traits<derived_alloc_t>;
		derived_alloc_t derived_alloc(b->m_allocator.allocator());
		derived_no_cv* ptr = const_cast<derived_no_cv*>(p);

		b->m_allocator.clear_allocator();
		derived_alloc_traits::destroy(derived_alloc, ptr);
		derived_alloc_traits::deallocate(derived_alloc, ptr, 1);
	}
}

template <typename Object, typename CounterPolicyT, typename Allocator>
template <typename Derived>
/* static */
void impl::intrusive_traits_impl<Object, CounterPolicyT, Allocator>::init_allocator(Derived* p, Allocator const& alloc) noexcept {
	base_t const* const b = p;
	b->m_allocator.init_allocator(alloc);
}

/**
 * @brief helper function for boost::intrusive_ptr reference counter management
 * @internal
 */
template <typename Derived, typename traits = impl::intrusive_traits<Derived>>
void intrusive_ptr_add_ref(Derived* p) noexcept {
	traits::add_ref(p);
}

/**
 * @brief helper function for boost::intrusive_ptr reference counter management
 * @internal
 */
template <typename Derived, typename traits = impl::intrusive_traits<Derived>>
void intrusive_ptr_release(Derived* p) noexcept {
	traits::release(p);
}

/**
 * allocate object of type `Derived` (which must derive from @ref intrusive_base) and
 * return a `boost::intrusive_ptr` to it.
 * @param alloc    Allocator to allocate object with
 * @param args     Arguments to pass to `Derived` constructor
 * @tparam Derived type of object to create
 */
template <typename Derived, typename traits = impl::intrusive_traits<Derived>, typename... Args>
boost::intrusive_ptr<Derived> allocate_intrusive(typename traits::allocator_t const& alloc, Args&&... args) {
	using alloc_t = typename traits::allocator_t;
	using derived_alloc_t = typename std::allocator_traits<alloc_t>::template rebind_alloc<Derived>;
	using derived_alloc_traits = std::allocator_traits<derived_alloc_t>;
	derived_alloc_t derived_alloc(alloc);

	typename derived_alloc_traits::pointer ptr = derived_alloc_traits::allocate(derived_alloc, 1);
	typename traits::base_t* base_ptr = ptr;
	try {
		derived_alloc_traits::construct(derived_alloc, ptr, std::forward<Args>(args)...);
		traits::init_allocator(base_ptr, alloc);
	} catch (...) {
		derived_alloc_traits::deallocate(derived_alloc, ptr, 1);
		throw;
	}

	return boost::intrusive_ptr<Derived>(ptr);
}

/**
 * @brief create a new object of type `Derived` which must derive from @ref intrusive_base)
 * using a default constructed allocator.
 * @param args     Arguments to forward to contructor of `Derived`
 * @tparam Derived type of object to create
 */
template <typename Derived, typename traits = impl::intrusive_traits<Derived>, typename... Args>
boost::intrusive_ptr<Derived> make_intrusive(Args&&... args) {
	using alloc_t = typename traits::allocator_t;
	return allocate_intrusive<Derived>(alloc_t(), std::forward<Args>(args)...);
}

template <typename Object, typename CounterPolicyT, typename Allocator>
template <typename Derived, typename... Args>
/* static */
boost::intrusive_ptr<Derived> intrusive_base<Object, CounterPolicyT, Allocator>::allocate(Allocator const& alloc, Args&&... args) {
	static_assert(std::is_base_of<Object, Derived>::value, "only create derived objects");
	return allocate_intrusive<Derived>(alloc, std::forward<Args>(args)...);
}

template <typename Object, typename CounterPolicyT, typename Allocator>
template <typename Derived, typename... Args>
/* static */
boost::intrusive_ptr<Derived> intrusive_base<Object, CounterPolicyT, Allocator>::create(Args&&... args) {
	static_assert(std::is_base_of<Object, Derived>::value, "only create derived objects");
	return make_intrusive<Derived>(std::forward<Args>(args)...);
}

__CANEY_MEMORYV1_END
<|endoftext|>


<commit_before>// ======================================================================== //
// Copyright 2009-2017 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#ifdef _WIN32
#  define WIN32_LEAN_AND_MEAN
#  include <windows.h> // for Sleep
#else
#  include <time.h>
#endif
#include <chrono>
#include <atomic>
#include <thread>

#include "BatchedIsendIrecvMessaging.h"
#include "../MPICommon.h"

namespace ospray {
  namespace mpi {
    namespace async {

      const int SEND_WINDOW_SIZE = 48;
      const int RECV_WINDOW_SIZE = 48;
      const int PROC_WINDOW_SIZE = 20;

      BatchedIsendIrecvImpl::Group::Group(MPI_Comm comm,
                                          Consumer *consumer,
                                          int32 tag)
        : async::Group(comm,consumer,tag),
          sendThread(this),
          procThread(this),
          recvThread(this),
          shouldExit(false)
      {
        sendThread.handle = std::thread([this](){this->sendThread.run();});
        procThread.handle = std::thread([this](){this->procThread.run();});
        recvThread.handle = std::thread([this](){this->recvThread.run();});
      }

      void BatchedIsendIrecvImpl::SendThread::run()
      {
        Group  &g = *group;
        Action *actions[SEND_WINDOW_SIZE];
        MPI_Request request[SEND_WINDOW_SIZE];

        while (1) {
          size_t numActions = 0;

          while (numActions == 0){
            numActions = g.sendQueue.getSomeFor(actions,
                                                SEND_WINDOW_SIZE,
                                                std::chrono::milliseconds(1));
            if (g.shouldExit.load())
              return;
          }

          for (size_t i = 0; i < numActions; i++) {
            Action *action = actions[i];
            SERIALIZED_MPI_CALL(Isend(action->data, action->size, MPI_BYTE,
                                      action->addr.rank, g.tag, g.comm,
                                      &request[i]));
          }

          // TODO: Is it ok to wait even if we're exiting? Maybe we'd just
          //       get send failed statuses back?
          SERIALIZED_MPI_CALL(Waitall(numActions, request,
                                      MPI_STATUSES_IGNORE));

          for (size_t i = 0; i < numActions; i++) {
            Action *action = actions[i];
            free(action->data);
            delete action;

            {
              std::lock_guard<std::mutex> lock(g.flushMutex);
              g.numMessagesDoneSending++;
              if (g.numMessagesDoneSending == g.numMessagesAskedToSend)
                g.isFlushedCondition.notify_one();
            }
          }
        }
      }

      void BatchedIsendIrecvImpl::RecvThread::run()
      {
        Group &g = *group;

        MPI_Request request[RECV_WINDOW_SIZE];
        Action *actions[RECV_WINDOW_SIZE];
        MPI_Status status;
        int numRequests = 0;
#ifdef _WIN32
        const DWORD sleep_time = 1; // ms --> much longer than 150us
#else
        const timespec sleep_time = timespec{0, 150000};
#endif

        while (1) {
          numRequests = 0;
          // wait for first message
          {
            int msgAvail = 0;
            while (!msgAvail) {
              SERIALIZED_MPI_CALL(Iprobe(MPI_ANY_SOURCE, g.tag, g.comm,
                                         &msgAvail, &status));

              if (g.shouldExit.load())
                return;

              if (msgAvail)
                break;

#ifdef _WIN32
              Sleep(sleep_time);
#else
              // TODO: Can we do a CMake feature test for this_thread::sleep_for
              //       and conditionally use nanosleep?
              nanosleep(&sleep_time, nullptr);
#endif
            }

            Action *action = new Action;
            action->addr = Address(&g, status.MPI_SOURCE);
            SERIALIZED_MPI_CALL(Get_count(&status, MPI_BYTE, &action->size));

            action->data = malloc(action->size);

            SERIALIZED_MPI_CALL(Irecv(action->data, action->size, MPI_BYTE,
                                      status.MPI_SOURCE, status.MPI_TAG,
                                      g.comm, &request[numRequests]));

            actions[numRequests++] = action;
          }

          // ... and add all the other ones that are outstanding, up
          // to max window size
          while (numRequests < RECV_WINDOW_SIZE) {
            int msgAvail;
            SERIALIZED_MPI_CALL(Iprobe(MPI_ANY_SOURCE, g.tag, g.comm,
                                       &msgAvail, &status));

            if (!msgAvail)
              break;

            Action *action = new Action;
            action->addr = Address(&g, status.MPI_SOURCE);

            SERIALIZED_MPI_CALL(Get_count(&status,MPI_BYTE,&action->size));

            action->data = malloc(action->size);

            SERIALIZED_MPI_CALL(Irecv(action->data, action->size, MPI_BYTE,
                                      status.MPI_SOURCE, status.MPI_TAG,
                                      g.comm, &request[numRequests]));

            actions[numRequests++] = action;
          }

          // TODO: Is it ok to wait even if we're exiting? Maybe we'd just get
          //       send failed statuses back?
          // now, have certain number of messages available...
          SERIALIZED_MPI_CALL(Waitall(numRequests, request,
                                      MPI_STATUSES_IGNORE));

          // OK, all actions are valid now
          g.recvQueue.putSome(&actions[0], numRequests);
        }
      }

      void BatchedIsendIrecvImpl::ProcThread::run()
      {
        Group *g = (Group *)this->group;
        while (1) {
          Action *actions[PROC_WINDOW_SIZE];
          size_t numActions = 0;

          while (numActions == 0) {
            numActions = g->recvQueue.getSomeFor(actions,
                                                 PROC_WINDOW_SIZE,
                                                 std::chrono::milliseconds(1));
            if (g->shouldExit.load()){
              return;
            }
          }

          for (size_t i = 0; i < numActions; i++) {
            Action *action = actions[i];
            g->consumer->process(action->addr, action->data, action->size);
            delete action;
          }
        }
      }

      void BatchedIsendIrecvImpl::Group::shutdown()
      {
        if (logMPI) {
          std::cout << "#osp:mpi:BatchIsendIrecvMessaging:Group shutting down"
                    << std::endl;
        }
        shouldExit.store(true);
        sendThread.handle.join();
        recvThread.handle.join();
        procThread.handle.join();
      }

      void BatchedIsendIrecvImpl::init()
      {
        mpi::world.barrier();

        if (logMPI) {
          printf("#osp:mpi:BatchedIsendIrecvMessaging started up %i/%i\n",
                 mpi::world.rank, mpi::world.size);
          fflush(0);
        }

        mpi::world.barrier();
      }

      void BatchedIsendIrecvImpl::shutdown()
      {
        mpi::world.barrier();

        if (logMPI) {
          printf("#osp:mpi:BatchedIsendIrecvMessaging shutting down %i/%i\n",
                 mpi::world.rank, mpi::world.size);
          fflush(0);
        }

        mpi::world.barrier();

        for (uint32_t i = 0; i < myGroups.size(); i++)
          myGroups[i]->shutdown();

        if (logMPI) {
          printf("#osp:mpi:BatchedIsendIrecvMessaging finalizing %i/%i\n",
                 mpi::world.rank, mpi::world.size);
        }

        SERIALIZED_MPI_CALL(Finalize());
      }

      async::Group *BatchedIsendIrecvImpl::createGroup(MPI_Comm comm,
                                                       Consumer *consumer,
                                                       int32 tag)
      {
        assert(consumer);
        Group *g = new Group(comm,consumer,tag);
        assert(g);
        myGroups.push_back(g);
        return g;
      }

      void BatchedIsendIrecvImpl::send(const Address &dest,
                                       void *msgPtr,
                                       int32 msgSize)
      {
        Action *action = new Action;
        action->addr   = dest;
        action->data   = msgPtr;
        action->size   = msgSize;

        Group *g = (Group *)dest.group;
        { std::lock_guard<std::mutex> lock(g->flushMutex);
          g->numMessagesAskedToSend++;
        }

        g->sendQueue.put(action);
      }

      /*! flushes all outgoing messages. note this currently does NOT
          check if there's message incomgin during the flushign ... */
      void BatchedIsendIrecvImpl::flush()
      {
        for (auto g : myGroups)
          g->flush();
      }

      void BatchedIsendIrecvImpl::Group::flush()
      {
        std::unique_lock<std::mutex> lock(flushMutex);
        isFlushedCondition.wait(lock,[&]{
          return (numMessagesDoneSending == numMessagesAskedToSend);
        });
      }

    } // ::ospray::mpi::async
  } // ::ospray::mpi
} // ::ospray
<commit_msg>try Waitsome instead of Waitall, data parallel still deadlocks...<commit_after>// ======================================================================== //
// Copyright 2009-2017 Intel Corporation                                    //
//                                                                          //
// Licensed under the Apache License, Version 2.0 (the "License");          //
// you may not use this file except in compliance with the License.         //
// You may obtain a copy of the License at                                  //
//                                                                          //
//     http://www.apache.org/licenses/LICENSE-2.0                           //
//                                                                          //
// Unless required by applicable law or agreed to in writing, software      //
// distributed under the License is distributed on an "AS IS" BASIS,        //
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
// See the License for the specific language governing permissions and      //
// limitations under the License.                                           //
// ======================================================================== //

#ifdef _WIN32
#  define WIN32_LEAN_AND_MEAN
#  include <windows.h> // for Sleep
#else
#  include <time.h>
#endif
#include <chrono>
#include <atomic>
#include <thread>

#include "BatchedIsendIrecvMessaging.h"
#include "../MPICommon.h"

namespace ospray {
  namespace mpi {
    namespace async {

      const int SEND_WINDOW_SIZE = 48;
      const int RECV_WINDOW_SIZE = 48;
      const int PROC_WINDOW_SIZE = 20;

      BatchedIsendIrecvImpl::Group::Group(MPI_Comm comm,
                                          Consumer *consumer,
                                          int32 tag)
        : async::Group(comm,consumer,tag),
          sendThread(this),
          procThread(this),
          recvThread(this),
          shouldExit(false)
      {
        sendThread.handle = std::thread([&](){sendThread.run();});
        procThread.handle = std::thread([&](){procThread.run();});
        recvThread.handle = std::thread([&](){recvThread.run();});
      }

      void BatchedIsendIrecvImpl::SendThread::run()
      {
        Group  &g = *group;
        Action *actions[SEND_WINDOW_SIZE];
        MPI_Request request[SEND_WINDOW_SIZE];

        while (1) {
          size_t numActions = 0;

          while (numActions == 0){
            numActions = g.sendQueue.getSomeFor(actions,
                                                SEND_WINDOW_SIZE,
                                                std::chrono::milliseconds(1));
            if (g.shouldExit.load())
              return;
          }

          for (size_t i = 0; i < numActions; i++) {
            Action *action = actions[i];
            SERIALIZED_MPI_CALL(Isend(action->data, action->size, MPI_BYTE,
                                      action->addr.rank, g.tag, g.comm,
                                      &request[i]));
          }

          // TODO: Is it ok to wait even if we're exiting? Maybe we'd just
          //       get send failed statuses back?
          #if 1
          int numCompletedTotal = 0;
          while (true) {
            int numCompleted = 0;
            int completedIndices[SEND_WINDOW_SIZE];
            SERIALIZED_MPI_CALL(Waitsome(numActions, request, &numCompleted,
                                         completedIndices,MPI_STATUSES_IGNORE));
            numCompletedTotal += numCompleted >= 0 ? numCompleted : 0;
            if (numCompletedTotal >= numActions)
              break;
          }
          #else
          SERIALIZED_MPI_CALL(Waitall(numActions, request,
                                      MPI_STATUSES_IGNORE));
          #endif

          for (size_t i = 0; i < numActions; i++) {
            Action *action = actions[i];
            free(action->data);
            delete action;

            {
              std::lock_guard<std::mutex> lock(g.flushMutex);
              g.numMessagesDoneSending++;
              if (g.numMessagesDoneSending == g.numMessagesAskedToSend)
                g.isFlushedCondition.notify_one();
            }
          }
        }
      }

      void BatchedIsendIrecvImpl::RecvThread::run()
      {
        Group &g = *group;

        MPI_Request request[RECV_WINDOW_SIZE];
        Action *actions[RECV_WINDOW_SIZE];
        MPI_Status status;
        int numRequests = 0;
#ifdef _WIN32
        const DWORD sleep_time = 1; // ms --> much longer than 150us
#else
        const timespec sleep_time = timespec{0, 150000};
#endif

        while (1) {
          numRequests = 0;
          // wait for first message
          {
            int msgAvail = 0;
            while (!msgAvail) {
              SERIALIZED_MPI_CALL(Iprobe(MPI_ANY_SOURCE, g.tag, g.comm,
                                         &msgAvail, &status));

              if (g.shouldExit.load())
                return;

              if (msgAvail)
                break;

#ifdef _WIN32
              Sleep(sleep_time);
#else
              // TODO: Can we do a CMake feature test for this_thread::sleep_for
              //       and conditionally use nanosleep?
              nanosleep(&sleep_time, nullptr);
#endif
            }

            Action *action = new Action;
            action->addr = Address(&g, status.MPI_SOURCE);
            SERIALIZED_MPI_CALL(Get_count(&status, MPI_BYTE, &action->size));

            action->data = malloc(action->size);

            SERIALIZED_MPI_CALL(Irecv(action->data, action->size, MPI_BYTE,
                                      status.MPI_SOURCE, status.MPI_TAG,
                                      g.comm, &request[numRequests]));

            actions[numRequests++] = action;
          }

          // ... and add all the other ones that are outstanding, up
          // to max window size
          while (numRequests < RECV_WINDOW_SIZE) {
            int msgAvail;
            SERIALIZED_MPI_CALL(Iprobe(MPI_ANY_SOURCE, g.tag, g.comm,
                                       &msgAvail, &status));

            if (!msgAvail)
              break;

            Action *action = new Action;
            action->addr = Address(&g, status.MPI_SOURCE);

            SERIALIZED_MPI_CALL(Get_count(&status,MPI_BYTE,&action->size));

            action->data = malloc(action->size);

            SERIALIZED_MPI_CALL(Irecv(action->data, action->size, MPI_BYTE,
                                      status.MPI_SOURCE, status.MPI_TAG,
                                      g.comm, &request[numRequests]));

            actions[numRequests++] = action;
          }

          // TODO: Is it ok to wait even if we're exiting? Maybe we'd just get
          //       send failed statuses back?
          // now, have certain number of messages available...
          #if 1
          int numCompletedTotal = 0;
          while (true) {
            int numCompleted = 0;
            int completedIndices[RECV_WINDOW_SIZE];
            SERIALIZED_MPI_CALL(Waitsome(numRequests, request, &numCompleted,
                                         completedIndices,MPI_STATUSES_IGNORE));
            numCompletedTotal += numCompleted >= 0 ? numCompleted : 0;
            if (numCompletedTotal >= numRequests)
              break;
          }
          #else
          SERIALIZED_MPI_CALL(Waitall(numRequests, request,
                                      MPI_STATUSES_IGNORE));
          #endif

          // OK, all actions are valid now
          g.recvQueue.putSome(&actions[0], numRequests);
        }
      }

      void BatchedIsendIrecvImpl::ProcThread::run()
      {
        Group *g = (Group *)this->group;
        while (1) {
          Action *actions[PROC_WINDOW_SIZE];
          size_t numActions = 0;

          while (numActions == 0) {
            numActions = g->recvQueue.getSomeFor(actions,
                                                 PROC_WINDOW_SIZE,
                                                 std::chrono::milliseconds(1));
            if (g->shouldExit.load()){
              return;
            }
          }

          for (size_t i = 0; i < numActions; i++) {
            Action *action = actions[i];
            g->consumer->process(action->addr, action->data, action->size);
            delete action;
          }
        }
      }

      void BatchedIsendIrecvImpl::Group::shutdown()
      {
        if (logMPI) {
          std::cout << "#osp:mpi:BatchIsendIrecvMessaging:Group shutting down"
                    << std::endl;
        }
        shouldExit.store(true);
        sendThread.handle.join();
        recvThread.handle.join();
        procThread.handle.join();
      }

      void BatchedIsendIrecvImpl::init()
      {
        mpi::world.barrier();

        if (logMPI) {
          printf("#osp:mpi:BatchedIsendIrecvMessaging started up %i/%i\n",
                 mpi::world.rank, mpi::world.size);
          fflush(0);
        }

        mpi::world.barrier();
      }

      void BatchedIsendIrecvImpl::shutdown()
      {
        mpi::world.barrier();

        if (logMPI) {
          printf("#osp:mpi:BatchedIsendIrecvMessaging shutting down %i/%i\n",
                 mpi::world.rank, mpi::world.size);
          fflush(0);
        }

        mpi::world.barrier();

        for (uint32_t i = 0; i < myGroups.size(); i++)
          myGroups[i]->shutdown();

        if (logMPI) {
          printf("#osp:mpi:BatchedIsendIrecvMessaging finalizing %i/%i\n",
                 mpi::world.rank, mpi::world.size);
        }

        SERIALIZED_MPI_CALL(Finalize());
      }

      async::Group *BatchedIsendIrecvImpl::createGroup(MPI_Comm comm,
                                                       Consumer *consumer,
                                                       int32 tag)
      {
        assert(consumer);
        Group *g = new Group(comm,consumer,tag);
        assert(g);
        myGroups.push_back(g);
        return g;
      }

      void BatchedIsendIrecvImpl::send(const Address &dest,
                                       void *msgPtr,
                                       int32 msgSize)
      {
        Action *action = new Action;
        action->addr   = dest;
        action->data   = msgPtr;
        action->size   = msgSize;

        Group *g = (Group *)dest.group;
        { std::lock_guard<std::mutex> lock(g->flushMutex);
          g->numMessagesAskedToSend++;
        }

        g->sendQueue.put(action);
      }

      /*! flushes all outgoing messages. note this currently does NOT
          check if there's message incomgin during the flushign ... */
      void BatchedIsendIrecvImpl::flush()
      {
        for (auto g : myGroups)
          g->flush();
      }

      void BatchedIsendIrecvImpl::Group::flush()
      {
        std::unique_lock<std::mutex> lock(flushMutex);
        isFlushedCondition.wait(lock,[&]{
          return (numMessagesDoneSending == numMessagesAskedToSend);
        });
      }

    } // ::ospray::mpi::async
  } // ::ospray::mpi
} // ::ospray
<|endoftext|>


<commit_before>/**
 * @file delegate.cpp
 * @author Robin Dietrich <me (at) invokr (dot) org>
 * @version 1.0
 *
 * @par License
 *    Alice Replay Parser
 *    Copyright 2014-2015 Robin Dietrich
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

#include <iostream>
#include <cstring>
#include <cstddef>
#include <catch.hpp>
#include "../../../src/alice2/util/delegate.hpp"

using namespace alice;

class mTest1 {
public:
    mTest1() {

    }
    mTest1(const mTest1&& m) {
        // Include this to make sure perfect forwarding works
        REQUIRE("Delegate Perfect Forwarding" == 0);
    }

    mTest1(mTest1&&) = default;

    int add(int x, int y, mTest1 m) {
        return x + y;
    }
};

TEST_CASE( "delegate", "[util/delegate.hpp]" ) {
    mTest1 t1;
    mTest1 t2;
    auto d = delegate<int (int, int, mTest1)>::fromMember<mTest1, &mTest1::add>(&t1);

    REQUIRE(d(1, 2, std::move(t2)) == 3);
}<commit_msg>Better delegate test cases<commit_after>/**
 * @file delegate.cpp
 * @author Robin Dietrich <me (at) invokr (dot) org>
 * @version 1.0
 *
 * @par License
 *    Alice Replay Parser
 *    Copyright 2014-2015 Robin Dietrich
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

#include <iostream>
#include <cstring>
#include <cstddef>
#include <catch.hpp>
#include "../../../src/alice2/util/delegate.hpp"

using namespace alice;

// Normal test
TEST_CASE( "delegate", "[util/delegate.hpp]" ) {
    class mTest1 {
    public:
        int add(int x, int y) {
            return x + y;
        }
    };

    mTest1 t1;
    auto d = delegate<int (int, int)>::fromMember<mTest1, &mTest1::add>(&t1);
    REQUIRE(d(1, 2) == 3);
}

// See if move constructor is prefered over the copy constructor when moving
TEST_CASE( "delegate_perfect_forwarding", "[util/delegate.hpp]" ) {
    class mTest2 {
    public:
        mTest2() {}

        mTest2(const mTest2& m) {
            #pragma unused(m)
            REQUIRE("Perfect forwarding for delegates not working" == 0);
        }

        mTest2(mTest2&&) = default;

        int add(int x, int y, mTest2 m) {
            #pragma unused(m)
            return x + y;
        }
    };

    mTest2 t2;
    auto d = delegate<int (int, int, mTest2)>::fromMember<mTest2, &mTest2::add>(&t2);
    REQUIRE(d(4, 5, std::move(t2)) == 9);
}<|endoftext|>


<commit_before>#include <cstring>
#include <typeinfo>
#include <limits>
#include <vector>
#include <map>
#include <sstream>
#include <fstream>
#include <iostream>

#include <unistd.h>
#include <sys/wait.h>

#include <tightdb.hpp>
#include <tightdb/impl/destroy_guard.hpp>
#include <tightdb/column_basic.hpp>
#include <tightdb/column_string.hpp>
#include <tightdb/column_string_enum.hpp>
#include <tightdb/column_mixed.hpp>
#include <tightdb/array_binary.hpp>
#include <tightdb/array_string_long.hpp>
#include <tightdb/lang_bind_helper.hpp>
#ifdef TIGHTDB_ENABLE_REPLICATION
#  include <tightdb/replication.hpp>
#  include <tightdb/commit_log.hpp>
#endif

#include "../test.hpp"
#include "../util/demangle.hpp"
#include "../util/random.hpp"
#include "../util/thread_wrapper.hpp"
#include "../util/random.hpp"

using namespace std;
using namespace tightdb;
using namespace tightdb::util;
using namespace tightdb::test_util;
using namespace tightdb::_impl;

TEST(Foo)
{
    SHARED_GROUP_TEST_PATH(path);
    UniquePtr<LangBindHelper::TransactLogRegistry> tlr(getWriteLogs(path));
    UniquePtr<Replication> repl(makeWriteLogCollector(path));
    SharedGroup sg(*repl);
    Group* group = const_cast<Group*>(&sg.begin_read());

    LangBindHelper::promote_to_write(sg, *tlr);

    TableRef class_EmployeeObject = group->get_table("class_EmployeeObject");
    TableRef class_CompanyObject = group->get_table("class_CompanyObject");

    class_EmployeeObject->add_column(tightdb::DataType(0), "age");
    class_CompanyObject->add_column_link(tightdb::DataType(13), "employees", *class_EmployeeObject);

    LangBindHelper::commit_and_continue_as_read(sg);

    LangBindHelper::promote_to_write(sg, *tlr);
    class_EmployeeObject->add_empty_row(2);
    class_CompanyObject->add_empty_row();
    {
        LinkViewRef ll = class_CompanyObject->get_linklist(0,0);
        ll->add(0);
        ll->add(1);
    }
    LangBindHelper::commit_and_continue_as_read(sg);

    LinkViewRef people_in_company = class_CompanyObject->get_linklist(0,0);

    LangBindHelper::promote_to_write(sg, *tlr);
    people_in_company->remove(0);
    LangBindHelper::commit_and_continue_as_read(sg);

    LangBindHelper::promote_to_write(sg, *tlr);
    people_in_company->clear();
    LangBindHelper::commit_and_continue_as_read(sg);
}

// ==15309== Stack overflow in thread 1: can't grow stack to 0x7fe001ffc
/*
TEST(Foo)
{
    SHARED_GROUP_TEST_PATH(path);
    UniquePtr<LangBindHelper::TransactLogRegistry> tlr(getWriteLogs(path));
    UniquePtr<Replication> repl(makeWriteLogCollector(path));
    SharedGroup sg(*repl);
    Group* group = const_cast<Group*>(&sg.begin_read());

    LangBindHelper::promote_to_write(sg, *tlr);

    TableRef class_EmployeeObject = group->get_table("class_EmployeeObject");
    TableRef class_CompanyObject = group->get_table("class_CompanyObject");

    class_EmployeeObject->add_column(tightdb::DataType(2), "name");
    class_EmployeeObject->add_column(tightdb::DataType(0), "age");
    class_EmployeeObject->add_column(tightdb::DataType(1), "hired");
    class_CompanyObject->add_column(tightdb::DataType(2), "name");
    class_CompanyObject->add_column_link(tightdb::DataType(13), "employees", *class_EmployeeObject);

    LangBindHelper::commit_and_continue_as_read(sg);

    LangBindHelper::promote_to_write(sg, *tlr);
    class_EmployeeObject->add_empty_row(2);
    class_CompanyObject->add_empty_row();
    {
        LinkViewRef ll = class_CompanyObject->get_linklist(1,0);
        ll->add(0);
        ll->add(1);
    }
    LangBindHelper::commit_and_continue_as_read(sg);

    LinkViewRef people_in_company = class_CompanyObject->get_linklist(1,0);

    LangBindHelper::promote_to_write(sg, *tlr);
    people_in_company->remove(0);
    LangBindHelper::commit_and_continue_as_read(sg);

    LangBindHelper::promote_to_write(sg, *tlr);
    people_in_company->clear();
    LangBindHelper::commit_and_continue_as_read(sg);
}
*/
<commit_msg>Fix for: Fixed link list bug causing corruption after LangBindHelper::commit_and_continue_as_read()<commit_after>#include <cstring>
#include <typeinfo>
#include <limits>
#include <vector>
#include <map>
#include <sstream>
#include <fstream>
#include <iostream>

#include <unistd.h>
#include <sys/wait.h>

#include <tightdb.hpp>
#include <tightdb/impl/destroy_guard.hpp>
#include <tightdb/column_basic.hpp>
#include <tightdb/column_string.hpp>
#include <tightdb/column_string_enum.hpp>
#include <tightdb/column_mixed.hpp>
#include <tightdb/array_binary.hpp>
#include <tightdb/array_string_long.hpp>
#include <tightdb/lang_bind_helper.hpp>
#ifdef TIGHTDB_ENABLE_REPLICATION
#  include <tightdb/replication.hpp>
#  include <tightdb/commit_log.hpp>
#endif

#include "../test.hpp"
#include "../util/demangle.hpp"
#include "../util/random.hpp"
#include "../util/thread_wrapper.hpp"
#include "../util/random.hpp"

using namespace std;
using namespace tightdb;
using namespace tightdb::util;
using namespace tightdb::test_util;
using namespace tightdb::_impl;
<|endoftext|>


<commit_before>#include "sparse_matrix.h"
#include "dense_matrix.h"
#include "project_matrix_store.h"

using namespace fm;
using namespace fm::detail;

int main(int argc, char *argv[])
{
	if (argc < 2) {
		fprintf(stderr, "test conf_file\n");
		exit(1);
	}

	std::string conf_file = argv[1];
	config_map::ptr configs = config_map::create(conf_file);
	init_flash_matrix(configs);

	sparse_project_matrix_store::ptr proj
		= sparse_project_matrix_store::create_sparse_rand(1000000, 100,
				matrix_layout_t::L_ROW, get_scalar_type<double>(), 0.001);
	size_t nnz = 0;
	double sum = 0;
	for (size_t i = 0; i < proj->get_num_portions(); i++) {
		matrix_store::const_ptr mat = proj;
		local_sparse_matrix_store::const_ptr portion
			= std::dynamic_pointer_cast<const local_sparse_matrix_store>(
					mat->get_portion(i));
		if (portion == NULL)
			continue;

		assert(portion->store_layout() == matrix_layout_t::L_ROW);
		std::vector<off_t> idxs;
		size_t local_nnz = 0;
		for (size_t j = 0; j < portion->get_num_rows(); j++) {
			const char *row = portion->get_row_nnz(j, idxs);
			if (row == NULL) {
				assert(idxs.size() == 0);
				continue;
			}

			const double *drow = (const double *) row;
			local_nnz += idxs.size();
			for (size_t k = 0; k < idxs.size(); k++) {
				assert(idxs[k] >= 0 && idxs[k] < portion->get_num_rows());
				sum += drow[k];
			}
		}
		assert(local_nnz == portion->get_nnz());
		nnz += portion->get_nnz();
	}
	assert(nnz == proj->get_nnz());
	printf("sum: %f\n", sum);

	dense_matrix::ptr data = dense_matrix::create_randu<double>(0, 1, 100,
			proj->get_num_rows(), matrix_layout_t::L_COL);
	dense_matrix::ptr proj_mat = dense_matrix::create(proj);
	dense_matrix::ptr res = data->multiply(*proj_mat);
	res->materialize_self();

	dense_matrix::ptr dense_proj = dense_matrix::create(proj->conv_dense());
	scalar_variable::ptr proj_sum = dense_proj->sum();
	printf("dense proj sum: %f\n", scalar_variable::get_val<double>(*proj_sum));
	dense_matrix::ptr res2 = data->multiply(*dense_proj);
	dense_matrix::ptr diff = res->minus(*res2);
	scalar_variable::ptr diff_sum = diff->abs()->sum();
	assert(diff_sum->get_type() == get_scalar_type<double>());
	printf("diff: %f\n", scalar_variable::get_val<double>(*diff_sum));

	destroy_flash_matrix();
}
<commit_msg>[Matrix]: fix unit test on projection matrix.<commit_after>#include "sparse_matrix.h"
#include "dense_matrix.h"
#include "project_matrix_store.h"

using namespace fm;
using namespace fm::detail;

int main(int argc, char *argv[])
{
	if (argc < 2) {
		fprintf(stderr, "test conf_file\n");
		exit(1);
	}

	std::string conf_file = argv[1];
	config_map::ptr configs = config_map::create(conf_file);
	init_flash_matrix(configs);

	sparse_project_matrix_store::ptr proj_store
		= sparse_project_matrix_store::create_sparse_rand(1000000, 100,
				matrix_layout_t::L_ROW, get_scalar_type<double>(), 0.001);
	size_t nnz = 0;
	double sum = 0;
	for (size_t i = 0; i < proj_store->get_num_portions(); i++) {
		matrix_store::const_ptr mat = proj_store;
		lsparse_row_matrix_store::const_ptr portion
			= std::dynamic_pointer_cast<const lsparse_row_matrix_store>(
					mat->get_portion(i));
		if (portion == NULL)
			continue;

		assert(portion->store_layout() == matrix_layout_t::L_ROW);
		std::vector<off_t> idxs;
		size_t local_nnz = 0;
		size_t orig_nrow = portion->get_num_rows();
		size_t num_portions = portion->get_num_rows() / 128;
		for (size_t pidx = 0; pidx < num_portions; pidx++) {
			size_t local_nrow = std::min(128UL, orig_nrow - pidx * 128);
			lsparse_row_matrix_store *mutable_portion
				= const_cast<lsparse_row_matrix_store *>(portion.get());
			mutable_portion->resize(pidx * 128, 0, local_nrow,
					portion->get_num_cols());
			size_t orig_local_nnz = local_nnz;
			for (size_t j = 0; j < portion->get_num_rows(); j++) {
				const char *row = portion->get_row_nnz(j, idxs);
				if (row == NULL) {
					assert(idxs.size() == 0);
					continue;
				}

				const double *drow = (const double *) row;
				local_nnz += idxs.size();
				for (size_t k = 0; k < idxs.size(); k++) {
					assert(idxs[k] >= 0 && idxs[k] < portion->get_num_rows());
					sum += drow[k];
				}
			}
		}
		assert(local_nnz == portion->get_nnz());
		nnz += portion->get_nnz();
	}
	assert(nnz == proj_store->get_nnz());
	printf("sum: %f\n", sum);

	dense_matrix::ptr mean = dense_matrix::create_randu<double>(
			0, 1, proj_store->get_num_rows(), 1, matrix_layout_t::L_COL);
	std::vector<dense_matrix::ptr> tmps(2);
	tmps[0] = mean;
	tmps[1] = dense_matrix::create(proj_store);
	dense_matrix::ptr proj = dense_matrix::cbind(tmps);

	dense_matrix::ptr data = dense_matrix::create_randu<double>(0, 1, 100,
			proj->get_num_rows(), matrix_layout_t::L_COL);
	dense_matrix::ptr res = data->multiply(*proj);
	res->materialize_self();

	dense_matrix::ptr dense_proj = dense_matrix::create(proj_store->conv_dense());
	tmps[0] = mean;
	tmps[1] = dense_proj;
	dense_proj = dense_matrix::cbind(tmps);

	scalar_variable::ptr proj_sum = dense_proj->sum();
	printf("dense proj sum: %f\n", scalar_variable::get_val<double>(*proj_sum));
	dense_matrix::ptr res2 = data->multiply(*dense_proj);
	dense_matrix::ptr diff = res->minus(*res2);
	scalar_variable::ptr diff_sum = diff->abs()->sum();
	assert(diff_sum->get_type() == get_scalar_type<double>());
	printf("diff: %f\n", scalar_variable::get_val<double>(*diff_sum));

	destroy_flash_matrix();
}
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium 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 "media/base/filter_host.h"
#include "media/filters/null_audio_renderer.h"

namespace media {

// The number of reads to perform during initialization for preroll purposes.
static const size_t kInitialReads = 16;

// The number of buffers we consume before sleeping.  By doing so we can sleep
// for longer, reducing CPU load and avoiding situations where audio samples
// are so short that the OS sleeps our thread for too long.
static const size_t kBuffersPerSleep = 4;

NullAudioRenderer::NullAudioRenderer()
    : decoder_(NULL),
      playback_rate_(0.0f),
      thread_(NULL),
      initialized_(false),
      shutdown_(false) {
}

NullAudioRenderer::~NullAudioRenderer() {
  Stop();
}

// static
bool NullAudioRenderer::IsMediaFormatSupported(
    const MediaFormat* media_format) {
  DCHECK(media_format);
  std::string mime_type;
  return media_format->GetAsString(MediaFormat::kMimeType, &mime_type) &&
      mime_type.compare(mime_type::kUncompressedAudio) == 0;
}

void NullAudioRenderer::Stop() {
  shutdown_ = true;
  if (thread_)
    PlatformThread::Join(thread_);
}

void NullAudioRenderer::SetPlaybackRate(float playback_rate) {
  playback_rate_ = playback_rate;
}

bool NullAudioRenderer::Initialize(AudioDecoder* decoder) {
  DCHECK(decoder);
  decoder_ = decoder;

  // It's safe to start the thread now because it simply sleeps when playback
  // rate is 0.0f.
  if (!PlatformThread::Create(0, this, &thread_))
    return false;

  // Schedule our initial reads.
  for (size_t i = 0; i < kInitialReads; ++i) {
    ScheduleRead();
  }

  // Defer initialization until all scheduled reads have completed.
  return true;
}

void NullAudioRenderer::SetVolume(float volume) {
  // Do nothing.
}

void NullAudioRenderer::OnAssignment(Buffer* buffer_in) {
  bool initialized = false;
  {
    AutoLock auto_lock(input_lock_);
    buffer_in->AddRef();
    input_queue_.push_back(buffer_in);
    DCHECK(input_queue_.size() <= kInitialReads);

    // See if we're finally initialized.
    // TODO(scherkus): handle end of stream.
    initialized = !initialized_ && input_queue_.size() == kInitialReads;
  }

  if (initialized) {
    initialized_ = true;
    host_->InitializationComplete();
  }
}

void NullAudioRenderer::ThreadMain() {
  // Loop until we're signaled to stop.
  while (!shutdown_) {
    base::TimeDelta timestamp;
    base::TimeDelta duration;
    int sleep_ms = 0;
    int released_buffers = 0;

    // Only consume buffers when actually playing.
    if (playback_rate_ > 0.0f) {
      AutoLock auto_lock(input_lock_);
      for (size_t i = 0; i < kBuffersPerSleep && !input_queue_.empty(); ++i) {
        scoped_refptr<Buffer> buffer = input_queue_.front();
        input_queue_.pop_front();
        buffer->Release();
        timestamp = buffer->GetTimestamp();
        duration += buffer->GetDuration();
        ++released_buffers;
      }
      // Apply the playback rate to our sleep duration.
      sleep_ms =
          static_cast<int>(floor(duration.InMillisecondsF() / playback_rate_));
    }

    // Schedule reads for every released buffer to maintain "playback".
    for (int i = 0; i < released_buffers; ++i) {
      ScheduleRead();
    }

    // Sleep and update the clock when we wake up.
    PlatformThread::Sleep(sleep_ms);
    if (timestamp.InMicroseconds() > 0) {
      host_->SetTime(timestamp);
    }
  }
}

void NullAudioRenderer::ScheduleRead() {
  host_->PostTask(NewRunnableMethod(decoder_, &AudioDecoder::Read,
      new AssignableBuffer<NullAudioRenderer, Buffer>(this)));
}

}  // namespace media
<commit_msg>Fixed NullAudioRenderer gcc break due to not including <cmath>.<commit_after>// Copyright (c) 2009 The Chromium 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 <cmath>

#include "media/base/filter_host.h"
#include "media/filters/null_audio_renderer.h"

namespace media {

// The number of reads to perform during initialization for preroll purposes.
static const size_t kInitialReads = 16;

// The number of buffers we consume before sleeping.  By doing so we can sleep
// for longer, reducing CPU load and avoiding situations where audio samples
// are so short that the OS sleeps our thread for too long.
static const size_t kBuffersPerSleep = 4;

NullAudioRenderer::NullAudioRenderer()
    : decoder_(NULL),
      playback_rate_(0.0f),
      thread_(NULL),
      initialized_(false),
      shutdown_(false) {
}

NullAudioRenderer::~NullAudioRenderer() {
  Stop();
}

// static
bool NullAudioRenderer::IsMediaFormatSupported(
    const MediaFormat* media_format) {
  DCHECK(media_format);
  std::string mime_type;
  return media_format->GetAsString(MediaFormat::kMimeType, &mime_type) &&
      mime_type.compare(mime_type::kUncompressedAudio) == 0;
}

void NullAudioRenderer::Stop() {
  shutdown_ = true;
  if (thread_)
    PlatformThread::Join(thread_);
}

void NullAudioRenderer::SetPlaybackRate(float playback_rate) {
  playback_rate_ = playback_rate;
}

bool NullAudioRenderer::Initialize(AudioDecoder* decoder) {
  DCHECK(decoder);
  decoder_ = decoder;

  // It's safe to start the thread now because it simply sleeps when playback
  // rate is 0.0f.
  if (!PlatformThread::Create(0, this, &thread_))
    return false;

  // Schedule our initial reads.
  for (size_t i = 0; i < kInitialReads; ++i) {
    ScheduleRead();
  }

  // Defer initialization until all scheduled reads have completed.
  return true;
}

void NullAudioRenderer::SetVolume(float volume) {
  // Do nothing.
}

void NullAudioRenderer::OnAssignment(Buffer* buffer_in) {
  bool initialized = false;
  {
    AutoLock auto_lock(input_lock_);
    buffer_in->AddRef();
    input_queue_.push_back(buffer_in);
    DCHECK(input_queue_.size() <= kInitialReads);

    // See if we're finally initialized.
    // TODO(scherkus): handle end of stream.
    initialized = !initialized_ && input_queue_.size() == kInitialReads;
  }

  if (initialized) {
    initialized_ = true;
    host_->InitializationComplete();
  }
}

void NullAudioRenderer::ThreadMain() {
  // Loop until we're signaled to stop.
  while (!shutdown_) {
    base::TimeDelta timestamp;
    base::TimeDelta duration;
    int sleep_ms = 0;
    int released_buffers = 0;

    // Only consume buffers when actually playing.
    if (playback_rate_ > 0.0f) {
      AutoLock auto_lock(input_lock_);
      for (size_t i = 0; i < kBuffersPerSleep && !input_queue_.empty(); ++i) {
        scoped_refptr<Buffer> buffer = input_queue_.front();
        input_queue_.pop_front();
        buffer->Release();
        timestamp = buffer->GetTimestamp();
        duration += buffer->GetDuration();
        ++released_buffers;
      }
      // Apply the playback rate to our sleep duration.
      sleep_ms =
          static_cast<int>(floor(duration.InMillisecondsF() / playback_rate_));
    }

    // Schedule reads for every released buffer to maintain "playback".
    for (int i = 0; i < released_buffers; ++i) {
      ScheduleRead();
    }

    // Sleep and update the clock when we wake up.
    PlatformThread::Sleep(sleep_ms);
    if (timestamp.InMicroseconds() > 0) {
      host_->SetTime(timestamp);
    }
  }
}

void NullAudioRenderer::ScheduleRead() {
  host_->PostTask(NewRunnableMethod(decoder_, &AudioDecoder::Read,
      new AssignableBuffer<NullAudioRenderer, Buffer>(this)));
}

}  // namespace media
<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium 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 <iostream>
#include <X11/Xlib.h>

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/scoped_ptr.h"
#include "base/thread.h"
#include "media/base/media.h"
#include "media/base/pipeline_impl.h"
#include "media/filters/audio_renderer_impl.h"
#include "media/filters/ffmpeg_audio_decoder.h"
#include "media/filters/ffmpeg_demuxer.h"
#include "media/filters/ffmpeg_video_decoder.h"
#include "media/filters/file_data_source.h"
#include "media/filters/null_audio_renderer.h"
#include "media/tools/player_x11/x11_video_renderer.h"

Display* g_display;
Window g_window;

// Initialize X11. Returns true if successful. This method creates the X11
// window. Further initialization is done in X11VideoRenderer.
bool InitX11() {
  g_display = XOpenDisplay(NULL);
  if (!g_display) {
    std::cout << "Error - cannot open display" << std::endl;
    return false;
  }

  // Get properties of the screen.
  int screen = DefaultScreen(g_display);
  int root_window = RootWindow(g_display, screen);

  // Creates the window.
  g_window = XCreateSimpleWindow(g_display, root_window, 1, 1, 100, 50, 0,
                                 BlackPixel(g_display, screen),
                                 BlackPixel(g_display, screen));
  XStoreName(g_display, g_window, "X11 Media Player");

  XSelectInput(g_display, g_window, ExposureMask | ButtonPressMask);
  XMapWindow(g_display, g_window);
  return true;
}

bool InitPipeline(MessageLoop* message_loop,
                  const char* filename, bool enable_audio,
                  scoped_refptr<media::PipelineImpl>* pipeline) {
  // Load media libraries.
  if (!media::InitializeMediaLibrary(FilePath())) {
    std::cout << "Unable to initialize the media library." << std::endl;
    return false;
  }

  // Create our filter factories.
  scoped_refptr<media::FilterFactoryCollection> factories =
      new media::FilterFactoryCollection();
  factories->AddFactory(media::FileDataSource::CreateFactory());
  factories->AddFactory(media::FFmpegAudioDecoder::CreateFactory());
  factories->AddFactory(media::FFmpegDemuxer::CreateFilterFactory());
  factories->AddFactory(media::FFmpegVideoDecoder::CreateFactory());
  factories->AddFactory(X11VideoRenderer::CreateFactory(g_display, g_window));

  if (enable_audio) {
    factories->AddFactory(media::AudioRendererImpl::CreateFilterFactory());
  } else {
    factories->AddFactory(media::NullAudioRenderer::CreateFilterFactory());
  }

  // Creates the pipeline and start it.
  *pipeline = new media::PipelineImpl(message_loop);
  (*pipeline)->Start(factories, filename, NULL);

  // Wait until the pipeline is fully initialized.
  while (true) {
    PlatformThread::Sleep(100);
    if ((*pipeline)->IsInitialized())
      break;
    if ((*pipeline)->GetError() != media::PIPELINE_OK) {
      (*pipeline)->Stop(NULL);
      return false;
    }
  }

  // And starts the playback.
  (*pipeline)->SetPlaybackRate(1.0f);
  return true;
}

int main(int argc, char** argv) {
  // Read arguments.
  if (argc == 1) {
    std::cout << "Usage: " << argv[0] << " --file=FILE [--audio]"
                 " [--alsa-device=DEVICE]" << std::endl;
    return 1;
  }

  // Read command line.
  CommandLine::Init(argc, argv);
  std::string filename =
      CommandLine::ForCurrentProcess()->GetSwitchValueASCII("file");
  bool enable_audio = CommandLine::ForCurrentProcess()->HasSwitch("audio");

  // Initialize X11.
  if (!InitX11())
    return 1;

  // Initialize the pipeline thread and the pipeline.
  base::AtExitManager at_exit;
  scoped_ptr<base::Thread> thread;
  scoped_refptr<media::PipelineImpl> pipeline;
  thread.reset(new base::Thread("PipelineThread"));
  thread->Start();
  if (InitPipeline(thread->message_loop(), filename.c_str(),
                   enable_audio, &pipeline)) {
    // Main loop of the application.
    while (true) {
      if (XPending(g_display)) {
        XEvent e;
        XNextEvent(g_display, &e);
        if (e.type == Expose) {
          // Tell the renderer to paint.
          DCHECK(X11VideoRenderer::instance());
          X11VideoRenderer::instance()->Paint();
        } else if (e.type == ButtonPress) {
          // Stop the playback.
          std::cout << "Stopping..." << std::endl;
          pipeline->Stop(NULL);
          break;
        }
      } else {
        // If there's no event in the queue, make an expose event.
        XEvent event;
        event.type = Expose;
        XSendEvent(g_display, g_window, true, ExposureMask, &event);

        // TODO(hclam): It is rather arbitrary to sleep for 10ms and wait
        // for the next event. We should submit an expose event when
        // a frame is available but not firing an expose event every 10ms.
        usleep(10000);
      }
    }
  }

  // Cleanup tasks.
  thread->Stop();
  XDestroyWindow(g_display, g_window);
  XCloseDisplay(g_display);
  return 0;
}
<commit_msg>Signal handler for player_x11 application<commit_after>// Copyright (c) 2009 The Chromium 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 <iostream>
#include <signal.h>
#include <X11/Xlib.h>

#include "base/at_exit.h"
#include "base/command_line.h"
#include "base/file_path.h"
#include "base/scoped_ptr.h"
#include "base/thread.h"
#include "media/base/media.h"
#include "media/base/pipeline_impl.h"
#include "media/filters/audio_renderer_impl.h"
#include "media/filters/ffmpeg_audio_decoder.h"
#include "media/filters/ffmpeg_demuxer.h"
#include "media/filters/ffmpeg_video_decoder.h"
#include "media/filters/file_data_source.h"
#include "media/filters/null_audio_renderer.h"
#include "media/tools/player_x11/x11_video_renderer.h"

Display* g_display = NULL;
Window g_window = 0;
bool g_running = false;

// Initialize X11. Returns true if successful. This method creates the X11
// window. Further initialization is done in X11VideoRenderer.
bool InitX11() {
  g_display = XOpenDisplay(NULL);
  if (!g_display) {
    std::cout << "Error - cannot open display" << std::endl;
    return false;
  }

  // Get properties of the screen.
  int screen = DefaultScreen(g_display);
  int root_window = RootWindow(g_display, screen);

  // Creates the window.
  g_window = XCreateSimpleWindow(g_display, root_window, 1, 1, 100, 50, 0,
                                 BlackPixel(g_display, screen),
                                 BlackPixel(g_display, screen));
  XStoreName(g_display, g_window, "X11 Media Player");

  XSelectInput(g_display, g_window, ExposureMask | ButtonPressMask);
  XMapWindow(g_display, g_window);
  return true;
}

bool InitPipeline(MessageLoop* message_loop,
                  const char* filename, bool enable_audio,
                  scoped_refptr<media::PipelineImpl>* pipeline) {
  // Load media libraries.
  if (!media::InitializeMediaLibrary(FilePath())) {
    std::cout << "Unable to initialize the media library." << std::endl;
    return false;
  }

  // Create our filter factories.
  scoped_refptr<media::FilterFactoryCollection> factories =
      new media::FilterFactoryCollection();
  factories->AddFactory(media::FileDataSource::CreateFactory());
  factories->AddFactory(media::FFmpegAudioDecoder::CreateFactory());
  factories->AddFactory(media::FFmpegDemuxer::CreateFilterFactory());
  factories->AddFactory(media::FFmpegVideoDecoder::CreateFactory());
  factories->AddFactory(X11VideoRenderer::CreateFactory(g_display, g_window));

  if (enable_audio) {
    factories->AddFactory(media::AudioRendererImpl::CreateFilterFactory());
  } else {
    factories->AddFactory(media::NullAudioRenderer::CreateFilterFactory());
  }

  // Creates the pipeline and start it.
  *pipeline = new media::PipelineImpl(message_loop);
  (*pipeline)->Start(factories, filename, NULL);

  // Wait until the pipeline is fully initialized.
  while (true) {
    PlatformThread::Sleep(100);
    if ((*pipeline)->IsInitialized())
      break;
    if ((*pipeline)->GetError() != media::PIPELINE_OK) {
      (*pipeline)->Stop(NULL);
      return false;
    }
  }

  // And starts the playback.
  (*pipeline)->SetPlaybackRate(1.0f);
  return true;
}

void TerminateHandler(int signal) {
  g_running = false;
}

int main(int argc, char** argv) {
  // Read arguments.
  if (argc == 1) {
    std::cout << "Usage: " << argv[0] << " --file=FILE [--audio]"
                 " [--alsa-device=DEVICE]" << std::endl;
    return 1;
  }

  // Read command line.
  CommandLine::Init(argc, argv);
  std::string filename =
      CommandLine::ForCurrentProcess()->GetSwitchValueASCII("file");
  bool enable_audio = CommandLine::ForCurrentProcess()->HasSwitch("audio");

  // Install the signal handler.
  signal(SIGTERM, &TerminateHandler);
  signal(SIGINT, &TerminateHandler);

  // Initialize X11.
  if (!InitX11())
    return 1;

  // Initialize the pipeline thread and the pipeline.
  base::AtExitManager at_exit;
  scoped_ptr<base::Thread> thread;
  scoped_refptr<media::PipelineImpl> pipeline;
  thread.reset(new base::Thread("PipelineThread"));
  thread->Start();
  if (InitPipeline(thread->message_loop(), filename.c_str(),
                   enable_audio, &pipeline)) {
    // Main loop of the application.
    g_running = true;
    while (g_running) {
      if (XPending(g_display)) {
        XEvent e;
        XNextEvent(g_display, &e);
        if (e.type == Expose) {
          // Tell the renderer to paint.
          DCHECK(X11VideoRenderer::instance());
          X11VideoRenderer::instance()->Paint();
        } else if (e.type == ButtonPress) {
          // Stop the playback.
          break;
        }
      } else {
        // If there's no event in the queue, make an expose event.
        XEvent event;
        event.type = Expose;
        XSendEvent(g_display, g_window, true, ExposureMask, &event);

        // TODO(hclam): It is rather arbitrary to sleep for 10ms and wait
        // for the next event. We should submit an expose event when
        // a frame is available but not firing an expose event every 10ms.
        usleep(10000);
      }
    }
  }

  std::cout << "Stopping..." << std::endl;
  pipeline->Stop(NULL);

  // Cleanup tasks.
  thread->Stop();
  XDestroyWindow(g_display, g_window);
  XCloseDisplay(g_display);
  return 0;
}
<|endoftext|>


<commit_before><commit_msg>Add declaration of atom macro<commit_after><|endoftext|>


<commit_before><commit_msg>Do not crash when the creation of a folder fails<commit_after><|endoftext|>


<commit_before>/*  Copyright (C) 2006 Imperial College London and others.

    Please see the AUTHORS file in the main source directory for a full list
    of copyright holders.

    Prof. C Pain
    Applied Modelling and Computation Group
    Department of Earth Science and Engineering
    Imperial College London

    amcgsoftware@imperial.ac.uk

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation,
    version 2.1 of the License.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
    USA
*/

#include <iostream>
#include <map>
#include <sstream>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

#include "confdefs.h"

#include "c++debug.h"

#ifdef HAVE_MPI
#include <mpi.h>
#endif

using namespace std;

extern "C"{
  void meshconv(const char* input_basename, size_t input_basename_len, const char* input_mesh_format,
                  size_t input_mesh_format_len, const char* output_mesh_format, size_t output_mesh_format_len);
}

void Usage(){
  cerr << "Usage: meshconv [OPTIONS] ... inputname \n"
       << "with 'inputname' being the basename of the input mesh file\n"
       << "\n"
       << "Must be run in serial!\n"
       << "\n"
       << "Options:\n"
       << "\n"
       << "-h\t\tDisplay this help\n"
       << "-i\t\tInput mesh format\n"
       << "-o\t\tOutput mesh format\n"
       << "-l\t\tWrite output to log files\n"
       << "-v\t\tVerbose mode\n"
       << "\n"
       << "With the options 'i' and 'o' being one of the following:\n"
       << " * triangle\n"
       << " * gmsh\n"
       << " * exodusii\n"
       << "whereas 'exodusii' is only allowed as an input-mesh-format." << endl;
}

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

#ifdef HAVE_MPI
  MPI::Init(argc, argv);
  // Undo some MPI init shenanigans
  chdir(getenv("PWD"));
#endif

  // Modified version of fldecomp argument parsing
  // Get any command line arguments
  // Reset optarg so we can detect changes
  optarg = NULL;
  char c;
  map<char, string> args;
  while((c = getopt(argc, argv, "i:o:hlv")) != -1){
    if (c != '?'){
      if(optarg == NULL){
        args[c] = "true";
      }else{
        args[c] = optarg;
      }
    }else{
      if(isprint(optopt)){
        cerr << "Unknown option " << optopt << endl;
      }else{
        cerr << "Unknown option " << hex << optopt << endl;
      }
      Usage();
      exit(-1);
    }
  }

  // Logging
  if(args.count('l')){
    int rank = 0;

#ifdef HAVE_MPI
    if(MPI::Is_initialized()){
      rank = MPI::COMM_WORLD.Get_rank();
    }
#endif

    ostringstream buffer;
    buffer << "meshconv.log-" << rank;
    if(freopen(buffer.str().c_str(), "w", stdout) == NULL){
      cerr << "Failed to redirect stdout" << endl;
      exit(-1);
    }
    buffer.str("");
    buffer << "meshconv.err-" << rank;
    if(freopen(buffer.str().c_str(), "w", stderr) == NULL){
      cerr << "Failed to redirect stderr" << endl;
      exit(-1);
    }
    buffer.str("");
  }

  // Help
  if(args.count('h')){
    Usage();
    exit(0);
  }

  // Verbosity
  int verbosity = 0;
  if(args.count('v') > 0){
    verbosity = 3;
  }
  set_global_debug_level_fc(&verbosity);

  // Input and output base names
  string input_basename;
  if(argc == optind + 2){
    input_basename = argv[optind + 1];
  }else if(argc == optind + 1){
    input_basename = argv[optind];
  }else{
    Usage();
    exit(-1);
  }

  // Input and output mesh formats:
  string input_mesh_format, output_mesh_format;
  if(args.count('i') == 0){
    Usage();
    exit(-1);
  }
  input_mesh_format = args['i'].c_str();

  if(args.count('o') == 0){
    Usage();
    exit(-1);
  }
  output_mesh_format = args['o'].c_str();

  // Stop the program if 'exodusii' was given as output format:
  if (output_mesh_format.compare("exodusii") == 0){
    cerr << "Error: ExodusII is only allowed as an INPUT mesh format." << endl;
    exit(-1);
  }

  size_t input_basename_len = input_basename.size();
  size_t input_mesh_format_len = input_mesh_format.size();
  size_t output_mesh_format_len = output_mesh_format.size();
  meshconv(input_basename.c_str(), input_basename_len, input_mesh_format.c_str(), input_mesh_format_len, output_mesh_format.c_str(), output_mesh_format_len);

#ifdef HAVE_MPI
  MPI::Finalize();
#endif

  return 0;
}
<commit_msg>Revision 4201 saw the parallel version of the meshconverter, this commit simply fixes the usage information accordingly.<commit_after>/*  Copyright (C) 2006 Imperial College London and others.

    Please see the AUTHORS file in the main source directory for a full list
    of copyright holders.

    Prof. C Pain
    Applied Modelling and Computation Group
    Department of Earth Science and Engineering
    Imperial College London

    amcgsoftware@imperial.ac.uk

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation,
    version 2.1 of the License.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
    USA
*/

#include <iostream>
#include <map>
#include <sstream>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

#include "confdefs.h"

#include "c++debug.h"

#ifdef HAVE_MPI
#include <mpi.h>
#endif

using namespace std;

extern "C"{
  void meshconv(const char* input_basename, size_t input_basename_len, const char* input_mesh_format,
                  size_t input_mesh_format_len, const char* output_mesh_format, size_t output_mesh_format_len);
}

void Usage(){
  cerr << "Usage: meshconv [OPTIONS] ... inputname \n"
       << "with 'inputname' being the basename of the input mesh file\n"
       << "\n"
       << "Options:\n"
       << "\n"
       << "-h\t\tDisplay this help\n"
       << "-i\t\tInput mesh format\n"
       << "-o\t\tOutput mesh format\n"
       << "-l\t\tWrite output to log files\n"
       << "-v\t\tVerbose mode\n"
       << "\n"
       << "With the options 'i' and 'o' being one of the following:\n"
       << " * triangle\n"
       << " * gmsh\n"
       << " * exodusii\n"
       << "whereas 'exodusii' is only allowed as an input-mesh-format." << endl;
}

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

#ifdef HAVE_MPI
  MPI::Init(argc, argv);
  // Undo some MPI init shenanigans
  chdir(getenv("PWD"));
#endif

  // Modified version of fldecomp argument parsing
  // Get any command line arguments
  // Reset optarg so we can detect changes
  optarg = NULL;
  char c;
  map<char, string> args;
  while((c = getopt(argc, argv, "i:o:hlv")) != -1){
    if (c != '?'){
      if(optarg == NULL){
        args[c] = "true";
      }else{
        args[c] = optarg;
      }
    }else{
      if(isprint(optopt)){
        cerr << "Unknown option " << optopt << endl;
      }else{
        cerr << "Unknown option " << hex << optopt << endl;
      }
      Usage();
      exit(-1);
    }
  }

  // Logging
  if(args.count('l')){
    int rank = 0;

#ifdef HAVE_MPI
    if(MPI::Is_initialized()){
      rank = MPI::COMM_WORLD.Get_rank();
    }
#endif

    ostringstream buffer;
    buffer << "meshconv.log-" << rank;
    if(freopen(buffer.str().c_str(), "w", stdout) == NULL){
      cerr << "Failed to redirect stdout" << endl;
      exit(-1);
    }
    buffer.str("");
    buffer << "meshconv.err-" << rank;
    if(freopen(buffer.str().c_str(), "w", stderr) == NULL){
      cerr << "Failed to redirect stderr" << endl;
      exit(-1);
    }
    buffer.str("");
  }

  // Help
  if(args.count('h')){
    Usage();
    exit(0);
  }

  // Verbosity
  int verbosity = 0;
  if(args.count('v') > 0){
    verbosity = 3;
  }
  set_global_debug_level_fc(&verbosity);

  // Input and output base names
  string input_basename;
  if(argc == optind + 2){
    input_basename = argv[optind + 1];
  }else if(argc == optind + 1){
    input_basename = argv[optind];
  }else{
    Usage();
    exit(-1);
  }

  // Input and output mesh formats:
  string input_mesh_format, output_mesh_format;
  if(args.count('i') == 0){
    Usage();
    exit(-1);
  }
  input_mesh_format = args['i'].c_str();

  if(args.count('o') == 0){
    Usage();
    exit(-1);
  }
  output_mesh_format = args['o'].c_str();

  // Stop the program if 'exodusii' was given as output format:
  if (output_mesh_format.compare("exodusii") == 0){
    cerr << "Error: ExodusII is only allowed as an INPUT mesh format." << endl;
    exit(-1);
  }

  size_t input_basename_len = input_basename.size();
  size_t input_mesh_format_len = input_mesh_format.size();
  size_t output_mesh_format_len = output_mesh_format.size();
  meshconv(input_basename.c_str(), input_basename_len, input_mesh_format.c_str(), input_mesh_format_len, output_mesh_format.c_str(), output_mesh_format_len);

#ifdef HAVE_MPI
  MPI::Finalize();
#endif

  return 0;
}
<|endoftext|>


<commit_before>// Autor: Hygor Jardim da Silva
// This example is based on the "wsn-ping6.cc" example.

#include <fstream>
#include "ns3/core-module.h"
#include "ns3/internet-module.h"
#include "ns3/sixlowpan-module.h"
#include "ns3/lr-wpan-module.h"
#include "ns3/internet-apps-module.h"
#include "ns3/mobility-module.h"

using namespace ns3;

NS_LOG_COMPONENT_DEFINE ("WSN");

int main (int argc, char **argv)
{
  bool verbose = false;

  CommandLine cmd;
  cmd.AddValue ("verbose", "turn on log components", verbose);
  cmd.Parse (argc, argv);

  if (verbose)
    {
      LogComponentEnable ("Ping6WsnExample", LOG_LEVEL_INFO);
    }

  NS_LOG_INFO ("Create Nodes");
  NodeContainer nodes;
  nodes.Create (2);

  NodeContainer ap;
  ap.Create (1);

  NodeContainer allnodes;
  allnodes.Add (nodes);
  allnodes.Add (ap);

  NS_LOG_INFO ("Create Mobility");
  MobilityHelper mobility;
  mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
                                 "MinX", DoubleValue (0.0), //onde inicia no eixo X
                                 "MinY", DoubleValue (0.0), //onde inicia no eixo Y
                                 "DeltaX", DoubleValue (20.0), // Distância entre nós
                                 "DeltaY", DoubleValue (20.0), // Distância entre nós
                                 "GridWidth", UintegerValue (5), // Quantidade de colunas em uma linha
                                 "LayoutType", StringValue ("RowFirst")); // Definindo posições em linha
  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
  mobility.Install (nodes);
  mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
                                 "MinX", DoubleValue (10.0), //
                                 "MinY", DoubleValue (10.0), //
                                 "DeltaX", DoubleValue (0.0), // Distância entre nós
                                 "DeltaY", DoubleValue (0.0), // Distância entre nós
                                 "GridWidth", UintegerValue (1), // Quantidade de colunas em uma linha
                                 "LayoutType", StringValue ("RowFirst"));
  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
  mobility.Install (ap);

  NS_LOG_INFO ("Create Channels");
  LrWpanHelper lrWpanHelper;
  NetDeviceContainer devContainer = lrWpanHelper.Install(allnodes);
  lrWpanHelper.AssociateToPan (lrwpanDevices, 10);

  NS_LOG_INFO ("Install Internet Stack");
  InternetStackHelper internetv6;
  internetv6.SetIpv4StackInstall (false);
  internetv6.Install (allnodes);
}<commit_msg>WSN 6Lowpan <commit_after>// Autor: Hygor Jardim da Silva
// This example is based on the "wsn-ping6.cc" example.

#include <fstream>
#include "ns3/core-module.h"
#include "ns3/internet-module.h"
#include "ns3/sixlowpan-module.h"
#include "ns3/network-module.h"
#include "ns3/applications-module.h"
#include "ns3/lr-wpan-module.h"
#include "ns3/internet-apps-module.h"
#include "ns3/mobility-module.h"

using namespace ns3;

NS_LOG_COMPONENT_DEFINE ("WSN");

int main (int argc, char **argv)
{
  bool verbose = false;

  CommandLine cmd;
  cmd.AddValue ("verbose", "turn on log components", verbose);
  cmd.Parse (argc, argv);

  if (verbose)
    {
      LogComponentEnable ("Ping6WsnExample", LOG_LEVEL_INFO);
    }

  NS_LOG_INFO ("Create Nodes");
  NodeContainer nodes;
  nodes.Create (25);

  NodeContainer ap;
  ap.Create (1);

  NodeContainer allnodes;
  allnodes.Add (ap);
  allnodes.Add (nodes);

  NS_LOG_INFO ("Create Mobility");
  MobilityHelper mobility;
  mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
                                 "MinX", DoubleValue (0.0), //onde inicia no eixo X
                                 "MinY", DoubleValue (0.0), //onde inicia no eixo Y
                                 "DeltaX", DoubleValue (20.0), // Distância entre nós
                                 "DeltaY", DoubleValue (20.0), // Distância entre nós
                                 "GridWidth", UintegerValue (5), // Quantidade de colunas em uma linha
                                 "LayoutType", StringValue ("RowFirst")); // Definindo posições em linha
  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
  mobility.Install (nodes);
  mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
                                 "MinX", DoubleValue (10.0), //
                                 "MinY", DoubleValue (10.0), //
                                 "DeltaX", DoubleValue (0.0), // Distância entre nós
                                 "DeltaY", DoubleValue (0.0), // Distância entre nós
                                 "GridWidth", UintegerValue (1), // Quantidade de colunas em uma linha
                                 "LayoutType", StringValue ("RowFirst"));
  mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
  mobility.Install (ap);

  NS_LOG_INFO ("Create Channels");
  LrWpanHelper lrWpanHelper;
  NetDeviceContainer devContainer = lrWpanHelper.Install(allnodes);
  lrWpanHelper.AssociateToPan (devContainer, 10);

  NS_LOG_INFO ("Install Internet Stack");
  InternetStackHelper internetv6;
  internetv6.SetIpv4StackInstall (false);
  internetv6.Install (allnodes);

  NS_LOG_INFO ("Install 6LoWPAN");
  SixLowPanHelper sixlowpan;
  NetDeviceContainer nodeNetDevice = sixlowpan.Install (devContainer);

  NS_LOG_INFO ("Assign Addresses");

  Address serverAddress;

  Ipv6AddressHelper ipv6;
  ipv6.SetBase (Ipv6Address ("2001:1::"), Ipv6Prefix (64));
  Ipv6InterfaceContainer nodeInterface = ipv6.Assign (nodeNetDevice);
  // nodeInterface.SetForwarding (1, true);
  serverAddress = Address(nodeInterface.GetAddress (1,1));

  NS_LOG_INFO ("Create Applications");

  uint16_t port = 9;
  UdpEchoServerHelper echoServer (port); // Porta que irá ouvir
  ApplicationContainer serverApps = echoServer.Install (allnodes.Get (1));
  serverApps.Start (Seconds (1.0));
  serverApps.Stop (Seconds (100));

  UdpEchoClientHelper echoClient (serverAddress, port);
  echoClient.SetAttribute ("MaxPackets", UintegerValue (100));
  echoClient.SetAttribute ("Interval", TimeValue (Seconds (0.1)));
  echoClient.SetAttribute ("PacketSize", StringValue ("500Kb"));
  ApplicationContainer clientApps = echoClient.Install (nodes); // Instala nos 20 nós estáticos
  clientApps.Start (Seconds (1.5));
  clientApps.Stop (Seconds (100.0));

  NS_LOG_INFO ("Run Simulation");
  Simulator::Stop (Seconds (101));
  Simulator::Run ();

  Simulator::Destroy ();
  NS_LOG_INFO ("Done");
  return 0;
}
<|endoftext|>