<commit_before>/**
 * @file
 */
#pragma once

#include "libbirch/Any.hpp"
#include "libbirch/Atomic.hpp"
#include "libbirch/type.hpp"
#include "libbirch/memory.hpp"

namespace libbirch {
/**
 * Shared object.
 *
 * @ingroup libbirch
 *
 * @tparam T Type, must derive from Any.
 *
 * Supports reference counted garbage collection. Cycles are collected by
 * periodically calling collect(); currently this must be done manually at
 * opportune times.
 *
 * @attention While Shared maintains a pointer to a referent object, it likes
 * to pretend it's not a pointer. This behavior differs from
 * [`std::shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr).
 * In particular, its default constructor does not initialize the pointer to
 * `nullptr`, but rather default-constructs an object of type `T` and sets the
 * pointer to that. Consider using a [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional/optional)
 * with a Shared value instead of `nullptr`.
 */
template<class T>
class Shared {
  template<class U> friend class Shared;
  friend class Marker;
  friend class Scanner;
  friend class Reacher;
  friend class Collector;
  friend class Spanner;
  friend class Bridger;
  friend class Copier;
  friend class BiconnectedCopier;
public:
  using value_type = T;

  /**
   * Default constructor. Constructs a new referent using the default
   * constructor.
   */
  Shared() :
      Shared(new T(), false) {
    //
  }

  /**
   * Constructor. Constructs a new referent with the given arguments. The
   * first is a placeholder (pass [`std::in_place`](https://en.cppreference.com/w/cpp/utility/in_place))
   * to distinguish this constructor from copy and move constructors.
   *
   * @note [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional/)
   * behaves similarly with regard to [`std::in_place`](https://en.cppreference.com/w/cpp/utility/in_place).
   */
  template<class... Args>
  Shared(std::in_place_t, Args&&... args) :
      Shared(new T(std::forward<Args>(args)...), false) {
    //
  }

  /**
   * Constructor.
   *
   * @param ptr Raw pointer.
   * @param b Is this a bridge?
   */
  Shared(T* ptr, const bool b = false) :
      ptr(ptr),
      b(b) {
    if (ptr) {
      ptr->incShared();
    }
  }

  /**
   * Copy constructor.
   */
  Shared(const Shared& o) : ptr(nullptr), b(false) {
    if (o.b) {
      if (biconnected_copy()) {
        replace(o.load());
        b = true;
      } else {
        replace(o.get());
        b = false;
      }
    } else {
      replace(o.load());
    }
  }

  /**
   * Generic copy constructor.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared(const Shared<U>& o) :
      Shared(o.get(), false) {
    //
  }

  /**
   * Move constructor.
   */
  Shared(Shared&& o) :
      ptr(o.ptr.exchange(nullptr)), b(o.b) {
    o.b = false;
  }

  /**
   * Generic move constructor.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared(Shared<U>&& o) :
      ptr(o.ptr.exchange(nullptr)), b(o.b) {
    o.b = false;
  }

  /**
   * Destructor.
   */
  ~Shared() {
    release();
  }

  /**
   * Copy assignment.
   */
  Shared& operator=(const Shared& o) {
    replace(o.get());
    b = false;
    return *this;
  }

  /**
   * Generic copy assignment.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared& operator=(const Shared<U>& o) {
    replace(o.get());
    b = false;
    return *this;
  }

  /**
   * Move assignment.
   */
  Shared& operator=(Shared&& o) {
    auto ptr = o.ptr.exchange(nullptr);
    auto old = this->ptr.exchange(ptr);
    if (old) {
      if (ptr == old) {
        old->decShared();
      } else {
        old->decShared();
      }
    }
    std::swap(b, o.b);
    return *this;
  }

  /**
   * Generic move assignment.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared& operator=(Shared<U>&& o) {
    auto ptr = o.ptr.exchange(nullptr);
    auto old = this->ptr.exchange(ptr);
    if (old) {
      if (ptr == old) {
        old->decShared();
      } else {
        old->decShared();
      }
    }
    std::swap(b, o.b);
    return *this;
  }

  /**
   * Value assignment.
   */
  template<class U, std::enable_if_t<is_value<U>::value,int> = 0>
  Shared<T>& operator=(const U& o) {
    *get() = o;
    return *this;
  }

  /**
   * Value assignment.
   */
  template<class U, std::enable_if_t<is_value<U>::value,int> = 0>
  const Shared<T>& operator=(const U& o) const {
    *get() = o;
    return *this;
  }

  /**
   * Is the pointer not null?
   *
   * This is used instead of an `operator bool()` so as not to conflict with
   * conversion operators in the referent type.
   */
  bool query() const {
    return load() != nullptr;
  }

  /**
   * Get the raw pointer.
   */
  T* get();

  /**
   * Get the raw pointer.
   */
  T* get() const {
    return const_cast<Shared<T>*>(this)->get();
  }

  /**
   * Get the raw pointer as const.
   */
  const T* read() const {
    return get();
  }

  /**
   * Deep copy. Finds bridges in the reachable graph then immediately copies
   * the subgraph up to the nearest reachable bridges, the remainder deferred
   * until needed.
   */
  Shared<T> copy();

  /**
   * Deep copy.
   */
  Shared<T> copy() const {
    return const_cast<Shared<T>*>(this)->copy();
  }

  /**
   * Deep copy. Copies the subgraph up to the nearest reachable bridges, the
   * remainder deferred until needed. Unlike #copy(), does not attempt to find
   * new bridges, but does use existing bridges. This is suitable if eager
   * copying, rather than lazy copying, is preferred, or for the second and
   * subsequent copies when replicating a graph multiple times, when the
   * bridge finding has already been completed by the first copy (using
   * #copy()).
   */
  Shared<T> copy2();

  /**
   * Deep copy.
   */
  Shared<T> copy2() const {
    return const_cast<Shared<T>*>(this)->copy2();
  }

  /**
   * Replace. Sets the raw pointer to a new value and returns the previous
   * value.
   */
  T* replace(T* ptr) {
    if (ptr) {
      ptr->incShared();
    }
    auto old = this->ptr.exchange(ptr);
    if (old) {
      if (ptr == old) {
        old->decShared();
      } else {
        old->decShared();
      }
    }
    b = false;
    return old;
  }

  /**
   * Release. Sets the raw pointer to null and returns the previous value.
   */
  T* release() {
    auto old = ptr.exchange(nullptr);
    if (old) {
      old->decShared();
    }
    b = false;
    return old;
  }

  /**
   * Dereference.
   */
  T& operator*() const {
    return *get();
  }

  /**
   * Member access.
   */
  T* operator->() const {
    return get();
  }

  /**
   * Call on referent.
   */
  template<class... Args>
  auto& operator()(Args&&... args) {
    return (*get())(std::forward<Args>(args)...);
  }

private:
  /**
   * Load the raw pointer as-is. Does not trigger copy-on-write.
   */
  T* load() const {
    return ptr.load();
  }

  /**
   * Store the raw pointer as-is. Does not update reference counts.
   */
  void store(T* o) {
    ptr.store(o);
  }

  /**
   * Raw pointer.
   */
  Atomic<T*> ptr;

  /**
   * Is this a bridge?
   */
  bool b;
};

template<class T>
struct is_value<Shared<T>> {
  static const bool value = false;
};

template<class T>
struct is_pointer<Shared<T>> {
  static const bool value = true;
};
}

#include "libbirch/Spanner.hpp"
#include "libbirch/Bridger.hpp"
#include "libbirch/Copier.hpp"
#include "libbirch/BiconnectedCopier.hpp"

template<class T>
T* libbirch::Shared<T>::get() {
  T* v = load();
  if (b) {
    b = false;
    if (v->numShared() > 1) {  // no need to copy for last reference
      /* the copy is of a biconnected component here, used the optimized
       * BiconnectedCopier for this */
      v = static_cast<T*>(BiconnectedCopier(v).visit(static_cast<Any*>(v)));
      replace(v);
    }
  }
  return v;
}

template<class T>
libbirch::Shared<T> libbirch::Shared<T>::copy() {
  /* find bridges */
  Spanner().visit(0, 1, *this);
  Bridger().visit(1, 0, *this);

  /* copy */
  return copy2();
}

template<class T>
libbirch::Shared<T> libbirch::Shared<T>::copy2() {
  Any* u = load();
  if (b) {
    return Shared<T>(static_cast<T*>(u), true);
  } else {
    /* the copy is *not* of a biconnected component here, use the
     * general-purpose Copier for this */
    return Shared<T>(static_cast<T*>(Copier().visit(u)), false);
  }
}
<commit_msg>Restored use of decSharedReachable() in Shared.<commit_after>/**
 * @file
 */
#pragma once

#include "libbirch/Any.hpp"
#include "libbirch/Atomic.hpp"
#include "libbirch/type.hpp"
#include "libbirch/memory.hpp"

namespace libbirch {
/**
 * Shared object.
 *
 * @ingroup libbirch
 *
 * @tparam T Type, must derive from Any.
 *
 * Supports reference counted garbage collection. Cycles are collected by
 * periodically calling collect(); currently this must be done manually at
 * opportune times.
 *
 * @attention While Shared maintains a pointer to a referent object, it likes
 * to pretend it's not a pointer. This behavior differs from
 * [`std::shared_ptr`](https://en.cppreference.com/w/cpp/memory/shared_ptr).
 * In particular, its default constructor does not initialize the pointer to
 * `nullptr`, but rather default-constructs an object of type `T` and sets the
 * pointer to that. Consider using a [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional/optional)
 * with a Shared value instead of `nullptr`.
 */
template<class T>
class Shared {
  template<class U> friend class Shared;
  friend class Marker;
  friend class Scanner;
  friend class Reacher;
  friend class Collector;
  friend class Spanner;
  friend class Bridger;
  friend class Copier;
  friend class BiconnectedCopier;
public:
  using value_type = T;

  /**
   * Default constructor. Constructs a new referent using the default
   * constructor.
   */
  Shared() :
      Shared(new T(), false) {
    //
  }

  /**
   * Constructor. Constructs a new referent with the given arguments. The
   * first is a placeholder (pass [`std::in_place`](https://en.cppreference.com/w/cpp/utility/in_place))
   * to distinguish this constructor from copy and move constructors.
   *
   * @note [`std::optional`](https://en.cppreference.com/w/cpp/utility/optional/)
   * behaves similarly with regard to [`std::in_place`](https://en.cppreference.com/w/cpp/utility/in_place).
   */
  template<class... Args>
  Shared(std::in_place_t, Args&&... args) :
      Shared(new T(std::forward<Args>(args)...), false) {
    //
  }

  /**
   * Constructor.
   *
   * @param ptr Raw pointer.
   * @param b Is this a bridge?
   */
  Shared(T* ptr, const bool b = false) :
      ptr(ptr),
      b(b) {
    if (ptr) {
      ptr->incShared();
    }
  }

  /**
   * Copy constructor.
   */
  Shared(const Shared& o) : ptr(nullptr), b(false) {
    if (o.b) {
      if (biconnected_copy()) {
        replace(o.load());
        b = true;
      } else {
        replace(o.get());
        b = false;
      }
    } else {
      replace(o.load());
    }
  }

  /**
   * Generic copy constructor.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared(const Shared<U>& o) :
      Shared(o.get(), false) {
    //
  }

  /**
   * Move constructor.
   */
  Shared(Shared&& o) :
      ptr(o.ptr.exchange(nullptr)), b(o.b) {
    o.b = false;
  }

  /**
   * Generic move constructor.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared(Shared<U>&& o) :
      ptr(o.ptr.exchange(nullptr)), b(o.b) {
    o.b = false;
  }

  /**
   * Destructor.
   */
  ~Shared() {
    release();
  }

  /**
   * Copy assignment.
   */
  Shared& operator=(const Shared& o) {
    replace(o.get());
    b = false;
    return *this;
  }

  /**
   * Generic copy assignment.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared& operator=(const Shared<U>& o) {
    replace(o.get());
    b = false;
    return *this;
  }

  /**
   * Move assignment.
   */
  Shared& operator=(Shared&& o) {
    auto ptr = o.ptr.exchange(nullptr);
    auto old = this->ptr.exchange(ptr);
    if (old) {
      if (ptr == old) {
        old->decSharedReachable();
      } else {
        old->decShared();
      }
    }
    std::swap(b, o.b);
    return *this;
  }

  /**
   * Generic move assignment.
   */
  template<class U, std::enable_if_t<std::is_base_of<T,U>::value,int> = 0>
  Shared& operator=(Shared<U>&& o) {
    auto ptr = o.ptr.exchange(nullptr);
    auto old = this->ptr.exchange(ptr);
    if (old) {
      if (ptr == old) {
        old->decSharedReachable();
      } else {
        old->decShared();
      }
    }
    std::swap(b, o.b);
    return *this;
  }

  /**
   * Value assignment.
   */
  template<class U, std::enable_if_t<is_value<U>::value,int> = 0>
  Shared<T>& operator=(const U& o) {
    *get() = o;
    return *this;
  }

  /**
   * Value assignment.
   */
  template<class U, std::enable_if_t<is_value<U>::value,int> = 0>
  const Shared<T>& operator=(const U& o) const {
    *get() = o;
    return *this;
  }

  /**
   * Is the pointer not null?
   *
   * This is used instead of an `operator bool()` so as not to conflict with
   * conversion operators in the referent type.
   */
  bool query() const {
    return load() != nullptr;
  }

  /**
   * Get the raw pointer.
   */
  T* get();

  /**
   * Get the raw pointer.
   */
  T* get() const {
    return const_cast<Shared<T>*>(this)->get();
  }

  /**
   * Get the raw pointer as const.
   */
  const T* read() const {
    return get();
  }

  /**
   * Deep copy. Finds bridges in the reachable graph then immediately copies
   * the subgraph up to the nearest reachable bridges, the remainder deferred
   * until needed.
   */
  Shared<T> copy();

  /**
   * Deep copy.
   */
  Shared<T> copy() const {
    return const_cast<Shared<T>*>(this)->copy();
  }

  /**
   * Deep copy. Copies the subgraph up to the nearest reachable bridges, the
   * remainder deferred until needed. Unlike #copy(), does not attempt to find
   * new bridges, but does use existing bridges. This is suitable if eager
   * copying, rather than lazy copying, is preferred, or for the second and
   * subsequent copies when replicating a graph multiple times, when the
   * bridge finding has already been completed by the first copy (using
   * #copy()).
   */
  Shared<T> copy2();

  /**
   * Deep copy.
   */
  Shared<T> copy2() const {
    return const_cast<Shared<T>*>(this)->copy2();
  }

  /**
   * Replace. Sets the raw pointer to a new value and returns the previous
   * value.
   */
  T* replace(T* ptr) {
    if (ptr) {
      ptr->incShared();
    }
    auto old = this->ptr.exchange(ptr);
    if (old) {
      if (ptr == old) {
        old->decSharedReachable();
      } else {
        old->decShared();
      }
    }
    b = false;
    return old;
  }

  /**
   * Release. Sets the raw pointer to null and returns the previous value.
   */
  T* release() {
    auto old = ptr.exchange(nullptr);
    if (old) {
      old->decShared();
    }
    b = false;
    return old;
  }

  /**
   * Dereference.
   */
  T& operator*() const {
    return *get();
  }

  /**
   * Member access.
   */
  T* operator->() const {
    return get();
  }

  /**
   * Call on referent.
   */
  template<class... Args>
  auto& operator()(Args&&... args) {
    return (*get())(std::forward<Args>(args)...);
  }

private:
  /**
   * Load the raw pointer as-is. Does not trigger copy-on-write.
   */
  T* load() const {
    return ptr.load();
  }

  /**
   * Store the raw pointer as-is. Does not update reference counts.
   */
  void store(T* o) {
    ptr.store(o);
  }

  /**
   * Raw pointer.
   */
  Atomic<T*> ptr;

  /**
   * Is this a bridge?
   */
  bool b;
};

template<class T>
struct is_value<Shared<T>> {
  static const bool value = false;
};

template<class T>
struct is_pointer<Shared<T>> {
  static const bool value = true;
};
}

#include "libbirch/Spanner.hpp"
#include "libbirch/Bridger.hpp"
#include "libbirch/Copier.hpp"
#include "libbirch/BiconnectedCopier.hpp"

template<class T>
T* libbirch::Shared<T>::get() {
  T* v = load();
  if (b) {
    b = false;
    if (v->numShared() > 1) {  // no need to copy for last reference
      /* the copy is of a biconnected component here, used the optimized
       * BiconnectedCopier for this */
      v = static_cast<T*>(BiconnectedCopier(v).visit(static_cast<Any*>(v)));
      replace(v);
    }
  }
  return v;
}

template<class T>
libbirch::Shared<T> libbirch::Shared<T>::copy() {
  /* find bridges */
  Spanner().visit(0, 1, *this);
  Bridger().visit(1, 0, *this);

  /* copy */
  return copy2();
}

template<class T>
libbirch::Shared<T> libbirch::Shared<T>::copy2() {
  Any* u = load();
  if (b) {
    return Shared<T>(static_cast<T*>(u), true);
  } else {
    /* the copy is *not* of a biconnected component here, use the
     * general-purpose Copier for this */
    return Shared<T>(static_cast<T*>(Copier().visit(u)), false);
  }
}
<|endoftext|>


<commit_before>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2014                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#ifndef CAF_IO_NETWORK_MULTIPLEXER_HPP
#define CAF_IO_NETWORK_MULTIPLEXER_HPP

#include <string>
#include <thread>
#include <functional>

#include "caf/extend.hpp"
#include "caf/memory_managed.hpp"

#include "caf/io/fwd.hpp"
#include "caf/io/accept_handle.hpp"
#include "caf/io/connection_handle.hpp"
#include "caf/io/network/native_socket.hpp"

#include "caf/mixin/memory_cached.hpp"

#include "caf/detail/memory.hpp"

namespace boost {
namespace asio {
class io_service;
} // namespace asio
} // namespace boost

namespace caf {
namespace io {
namespace network {

/**
 * Low-level backend for IO multiplexing.
 */
class multiplexer {
 public:
  virtual ~multiplexer();

  /**
   * Creates a new TCP doorman from a native socket handle.
   */
  virtual connection_handle add_tcp_scribe(broker* ptr, native_socket fd) = 0;

  /**
   * Tries to connect to host `h` on given `port` and returns a
   * new scribe managing the connection on success.
   */
  virtual connection_handle add_tcp_scribe(broker* ptr, const std::string& host,
                                           uint16_t port) = 0;

  /**
   * Creates a new TCP doorman from a native socket handle.
   */
  virtual accept_handle add_tcp_doorman(broker* ptr, native_socket fd) = 0;

  /**
   * Tries to create a new TCP doorman running on port `p`, optionally
   * accepting only connections from IP address `in`.
   */
  virtual accept_handle add_tcp_doorman(broker* ptr, uint16_t port,
                                        const char* in = nullptr) = 0;

  /**
   * Simple wrapper for runnables
   */
  struct runnable : extend<memory_managed>::with<mixin::memory_cached> {
    virtual void run() = 0;
    virtual ~runnable();
  };

  using runnable_ptr = std::unique_ptr<runnable, detail::disposer>;

  /**
   * Makes sure the multipler does not exit its event loop until
   * the destructor of `supervisor` has been called.
   */
  struct supervisor {
   public:
    virtual ~supervisor();
  };

  using supervisor_ptr = std::unique_ptr<supervisor>;

  /**
   * Creates a supervisor to keep the event loop running.
   */
  virtual supervisor_ptr make_supervisor() = 0;

  /**
   * Creates an instance using the networking backend compiled with CAF.
   */
  static std::unique_ptr<multiplexer> make();

  /**
   * Runs the multiplexers event loop.
   */
  virtual void run() = 0;

  /**
   * Invokes @p fun in the multiplexer's event loop.
   */
  template <class F>
  void dispatch(F fun) {
    if (std::this_thread::get_id() == thread_id()) {
      fun();
      return;
    }
    post(std::move(fun));
  }

  /**
   * Invokes @p fun in the multiplexer's event loop.
   */
  template <class F>
  void post(F fun) {
    struct impl : runnable {
      F f;
      impl(F&& mf) : f(std::move(mf)) { }
      void run() override {
        f();
      }
    };
    dispatch_runnable(runnable_ptr{detail::memory::create<impl>(std::move(fun))});
  }

  /**
   * Retrieves a pointer to the implementation or `nullptr` if CAF was
   * compiled using the default backend.
   */
  virtual boost::asio::io_service* pimpl();

  inline const std::thread::id& thread_id() const {
    return m_tid;
  }

  inline void thread_id(std::thread::id tid) {
    m_tid = std::move(tid);
  }

 protected:
  /**
   * Implementation-specific dispatching to the multiplexer's thread.
   */
  virtual void dispatch_runnable(runnable_ptr ptr) = 0;

  /**
   * Must be set by the subclass.
   */
  std::thread::id m_tid;
};

using multiplexer_ptr = std::unique_ptr<multiplexer>;

} // namespace network
} // namespace io
} // namespace caf

#endif // CAF_IO_NETWORK_MULTIPLEXER_HPP
<commit_msg>Fix class/struct mismatch<commit_after>/******************************************************************************
 *                       ____    _    _____                                   *
 *                      / ___|  / \  |  ___|    C++                           *
 *                     | |     / _ \ | |_       Actor                         *
 *                     | |___ / ___ \|  _|      Framework                     *
 *                      \____/_/   \_|_|                                      *
 *                                                                            *
 * Copyright (C) 2011 - 2014                                                  *
 * Dominik Charousset <dominik.charousset (at) haw-hamburg.de>                *
 *                                                                            *
 * Distributed under the terms and conditions of the BSD 3-Clause License or  *
 * (at your option) under the terms and conditions of the Boost Software      *
 * License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE.       *
 *                                                                            *
 * If you did not receive a copy of the license files, see                    *
 * http://opensource.org/licenses/BSD-3-Clause and                            *
 * http://www.boost.org/LICENSE_1_0.txt.                                      *
 ******************************************************************************/

#ifndef CAF_IO_NETWORK_MULTIPLEXER_HPP
#define CAF_IO_NETWORK_MULTIPLEXER_HPP

#include <string>
#include <thread>
#include <functional>

#include "caf/extend.hpp"
#include "caf/memory_managed.hpp"

#include "caf/io/fwd.hpp"
#include "caf/io/accept_handle.hpp"
#include "caf/io/connection_handle.hpp"
#include "caf/io/network/native_socket.hpp"

#include "caf/mixin/memory_cached.hpp"

#include "caf/detail/memory.hpp"

namespace boost {
namespace asio {
class io_service;
} // namespace asio
} // namespace boost

namespace caf {
namespace io {
namespace network {

/**
 * Low-level backend for IO multiplexing.
 */
class multiplexer {
 public:
  virtual ~multiplexer();

  /**
   * Creates a new TCP doorman from a native socket handle.
   */
  virtual connection_handle add_tcp_scribe(broker* ptr, native_socket fd) = 0;

  /**
   * Tries to connect to host `h` on given `port` and returns a
   * new scribe managing the connection on success.
   */
  virtual connection_handle add_tcp_scribe(broker* ptr, const std::string& host,
                                           uint16_t port) = 0;

  /**
   * Creates a new TCP doorman from a native socket handle.
   */
  virtual accept_handle add_tcp_doorman(broker* ptr, native_socket fd) = 0;

  /**
   * Tries to create a new TCP doorman running on port `p`, optionally
   * accepting only connections from IP address `in`.
   */
  virtual accept_handle add_tcp_doorman(broker* ptr, uint16_t port,
                                        const char* in = nullptr) = 0;

  /**
   * Simple wrapper for runnables
   */
  struct runnable : extend<memory_managed>::with<mixin::memory_cached> {
    virtual void run() = 0;
    virtual ~runnable();
  };

  using runnable_ptr = std::unique_ptr<runnable, detail::disposer>;

  /**
   * Makes sure the multipler does not exit its event loop until
   * the destructor of `supervisor` has been called.
   */
  class supervisor {
   public:
    virtual ~supervisor();
  };

  using supervisor_ptr = std::unique_ptr<supervisor>;

  /**
   * Creates a supervisor to keep the event loop running.
   */
  virtual supervisor_ptr make_supervisor() = 0;

  /**
   * Creates an instance using the networking backend compiled with CAF.
   */
  static std::unique_ptr<multiplexer> make();

  /**
   * Runs the multiplexers event loop.
   */
  virtual void run() = 0;

  /**
   * Invokes @p fun in the multiplexer's event loop.
   */
  template <class F>
  void dispatch(F fun) {
    if (std::this_thread::get_id() == thread_id()) {
      fun();
      return;
    }
    post(std::move(fun));
  }

  /**
   * Invokes @p fun in the multiplexer's event loop.
   */
  template <class F>
  void post(F fun) {
    struct impl : runnable {
      F f;
      impl(F&& mf) : f(std::move(mf)) { }
      void run() override {
        f();
      }
    };
    dispatch_runnable(runnable_ptr{detail::memory::create<impl>(std::move(fun))});
  }

  /**
   * Retrieves a pointer to the implementation or `nullptr` if CAF was
   * compiled using the default backend.
   */
  virtual boost::asio::io_service* pimpl();

  inline const std::thread::id& thread_id() const {
    return m_tid;
  }

  inline void thread_id(std::thread::id tid) {
    m_tid = std::move(tid);
  }

 protected:
  /**
   * Implementation-specific dispatching to the multiplexer's thread.
   */
  virtual void dispatch_runnable(runnable_ptr ptr) = 0;

  /**
   * Must be set by the subclass.
   */
  std::thread::id m_tid;
};

using multiplexer_ptr = std::unique_ptr<multiplexer>;

} // namespace network
} // namespace io
} // namespace caf

#endif // CAF_IO_NETWORK_MULTIPLEXER_HPP
<|endoftext|>


<commit_before>#include <iostream>
#include <string>

using namespace std;

bool isSignMagNegative(unsigned int n) {
   unsigned int signBit = ((n >> 31) & 0x1);
   if (signBit == 1) {
     cout << "true" << endl;
     return true;
   } else {
     cout << "false" << endl;
     return false;
   }
}

unsigned int toTwosComplement(unsigned int n) {
   if (isSignMagNegative(n) == true) {
      unsigned int twosComplement = ((~(n & 0x7fffffff)) + 1);
      return twosComplement;
   } else {
      return w;
   }
}

int main() {
   unsigned int n = 0;
   cin >> n;
   toTwosComplement(n);
}
<commit_msg>minor changes<commit_after>//==============================================================================
// Two's Complement
//
// @description: Makefile for twoscomplement.cc
// @author: Elisha Lai
// @version: 1.0 24/09/2015
//==============================================================================

#include <iostream>
#include <string>

using namespace std;

bool isSignMagNegative(unsigned int n) {
   unsigned int signBit = ((n >> 31) & 0x1);
   if (signBit == 1) {
     cout << "true" << endl;
     return true;
   } else {
     cout << "false" << endl;
     return false;
   } // if
} // isSignMagNegative

unsigned int toTwosComplement(unsigned int n) {
   if (isSignMagNegative(n) == true) {
      unsigned int twosComplement = ((~(n & 0x7fffffff)) + 1);
      return twosComplement;
   } else {
      return w;
   } // if
} // toTwosComplement

int main() {
   unsigned int n = 0;
   cin >> n;
   toTwosComplement(n);
} // main

<|endoftext|>


<commit_before>/*
 This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.

In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

For more information, please refer to <http://unlicense.org>
*/

#include "Daemon.hh"

Daemon::Daemon(const std::string &path)
    : _local(path, DomainSocket::SERVER), _run(false)
{
}

Daemon::~Daemon(void)
{
    for (DomainSocket::iterator it = _clients.begin; it < _clients.end(); ++it)
    {
        delete *it;
    }
}

void Daemon::start(void)
{
    _run = true;
    while (_run)
    {
        handleSockets();
    }
    std::cout << "Server shutdown" << std::endl;
}

void Daemon::handleSockets(void)
{
    fd_set              readfds;
    fd_set              writefds;
    int                 fd_max;
    struct timeval      tv;

    fd_max = initSelect(&tv, &readfds, &writefds);
    if (::select(fd_max, &readfds, NULL, NULL, &tv) == -1)
    {
        throw std::runtime_error(std::string("Select Error : ") + ::strerror(errno));
    }
    else
    {
        // If something to read on stdin
        if (FD_ISSET(0, &readfds))
            eventTerminal();
        // If new client connect
        if (FD_ISSET(_local.fd(), &readfds))
            eventServer();
        // Check clients's socket
        eventClients(&readfds, &writefds);
    }

}

int Daemon::initSelect(struct timeval *tv, fd_set *readfds, fd_set *writefds)
{
    int     fd_max = _local.fd();

    // Timeout 100 ms
    tv->tv_sec = 0;
    tv->tv_usec = 100;

    // Initialize bits field for select
    FD_ZERO(readfds);
    FD_SET(_local.fd(), readfds);
    FD_SET(0, readfds);
    if (writefds != NULL)
    {
        FD_ZERO(writefds);
        FD_SET(_local.fd(), writefds);
    }
    for (DomainSocket *client : _clients)
    {
        FD_SET(client->fd(), readfds);
        if (writefds != NULL)
            FD_SET(client->fd(), writefds);
        // Check if client's fd is greater than actual fd_max
        fd_max = (fd_max < client->fd()) ? client->fd() : fd_max;
    }
    return fd_max + 1;
}

void Daemon::eventTerminal(void)
{
    std::string     msg;

    std::cin >> msg;
    if (msg == "exit")
    {
        _run = false;
    }
}

void Daemon::eventServer(void)
{
    DomainSocket    *client;

    try
    {
        client = _local.acceptClient();
        _clients.push_back(client);
    }
    catch (std::runtime_error &e)
    {
        std::cout << e.what() << std::endl;
    }
}

void Daemon::eventClients(fd_set *readfds, fd_set *writefds)
{
    std::string         msg;

    for (std::vector<DomainSocket*>::iterator it = _clients.begin(); it < _clients.end(); ++it)
    {
        // Something to write on client socket
        if (FD_ISSET((*it)->fd(), writefds))
        {
            if (_msgs.size())
            {
                try
                {
                    (*it)->sendMsg(_msgs.back());
                    _msgs.pop_back();
                }
                catch (std::runtime_error &e)
                {
                    std::cout << e.what() << std::endl;
                }
            }
        }
        // Something to read on client socket
        if (FD_ISSET((*it)->fd(), readfds))
        {
            try
            {
                _msgs.push_back((*it)->recvMsg());
            }
            catch (DomainSocket::Disconnected &e)
            {
                delete (*it);
                _clients.erase(it);
                it = _clients.begin();
            }
            catch (std::runtime_error &e)
            {
                std::cout << e.what() << std::endl;
            }
        }
    }
}

int main(int ac, char **av)
{
    if (ac != 2)
    {
        std::cout << "Usage : " << av[0] << " <socket_path>" << std::endl;
        return 1;
    }

    try
    {
        Daemon      d(av[1]);

        d.start();
    }
    catch (std::runtime_error &e)
    {

    }

    return 0;
}
<commit_msg>C++98 compatibility<commit_after>/*
 This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.

In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

For more information, please refer to <http://unlicense.org>
*/

#include "Daemon.hh"

Daemon::Daemon(const std::string &path)
    : _local(path, DomainSocket::SERVER), _run(false)
{
}

Daemon::~Daemon(void)
{
    for (DomainSocket::iterator it = _clients.begin; it < _clients.end(); ++it)
    {
        delete *it;
    }
}

void Daemon::start(void)
{
    _run = true;
    while (_run)
    {
        handleSockets();
    }
    std::cout << "Server shutdown" << std::endl;
}

void Daemon::handleSockets(void)
{
    fd_set              readfds;
    fd_set              writefds;
    int                 fd_max;
    struct timeval      tv;

    fd_max = initSelect(&tv, &readfds, &writefds);
    if (::select(fd_max, &readfds, NULL, NULL, &tv) == -1)
    {
        throw std::runtime_error(std::string("Select Error : ") + ::strerror(errno));
    }
    else
    {
        // If something to read on stdin
        if (FD_ISSET(0, &readfds))
            eventTerminal();
        // If new client connect
        if (FD_ISSET(_local.fd(), &readfds))
            eventServer();
        // Check clients's socket
        eventClients(&readfds, &writefds);
    }

}

int Daemon::initSelect(struct timeval *tv, fd_set *readfds, fd_set *writefds)
{
    int     fd_max = _local.fd();

    // Timeout 100 ms
    tv->tv_sec = 0;
    tv->tv_usec = 100;

    // Initialize bits field for select
    FD_ZERO(readfds);
    FD_SET(_local.fd(), readfds);
    FD_SET(0, readfds);
    if (writefds != NULL)
    {
        FD_ZERO(writefds);
        FD_SET(_local.fd(), writefds);
    }
    for (DomainSocket::iterator it = _clients.begin; it < _clients.end(); ++it)
    {
        FD_SET((*it)->fd(), readfds);
        if (writefds != NULL)
            FD_SET((*it)->fd(), writefds);
        // Check if client's fd is greater than actual fd_max
        fd_max = (fd_max < (*it)->fd()) ? (*it)->fd() : fd_max;
    }
    return fd_max + 1;
}

void Daemon::eventTerminal(void)
{
    std::string     msg;

    std::cin >> msg;
    if (msg == "exit")
    {
        _run = false;
    }
}

void Daemon::eventServer(void)
{
    DomainSocket    *client;

    try
    {
        client = _local.acceptClient();
        _clients.push_back(client);
    }
    catch (std::runtime_error &e)
    {
        std::cout << e.what() << std::endl;
    }
}

void Daemon::eventClients(fd_set *readfds, fd_set *writefds)
{
    std::string         msg;

    for (std::vector<DomainSocket*>::iterator it = _clients.begin(); it < _clients.end(); ++it)
    {
        // Something to write on client socket
        if (FD_ISSET((*it)->fd(), writefds))
        {
            if (_msgs.size())
            {
                try
                {
                    (*it)->sendMsg(_msgs.back());
                    _msgs.pop_back();
                }
                catch (std::runtime_error &e)
                {
                    std::cout << e.what() << std::endl;
                }
            }
        }
        // Something to read on client socket
        if (FD_ISSET((*it)->fd(), readfds))
        {
            try
            {
                _msgs.push_back((*it)->recvMsg());
            }
            catch (DomainSocket::Disconnected &e)
            {
                delete (*it);
                _clients.erase(it);
                it = _clients.begin();
            }
            catch (std::runtime_error &e)
            {
                std::cout << e.what() << std::endl;
            }
        }
    }
}

int main(int ac, char **av)
{
    if (ac != 2)
    {
        std::cout << "Usage : " << av[0] << " <socket_path>" << std::endl;
        return 1;
    }

    try
    {
        Daemon      d(av[1]);

        d.start();
    }
    catch (std::runtime_error &e)
    {

    }

    return 0;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "runconfigurationaspects.h"

#include "project.h"
#include "runconfiguration.h"
#include "environmentaspect.h"

#include <coreplugin/coreconstants.h>

#include <utils/fancylineedit.h>
#include <utils/pathchooser.h>

#include <QCheckBox>
#include <QLineEdit>
#include <QDebug>
#include <QFormLayout>
#include <QLabel>
#include <QToolButton>

using namespace Utils;

namespace ProjectExplorer {

/*!
    \class ProjectExplorer::TerminalAspect
*/

TerminalAspect::TerminalAspect(RunConfiguration *runConfig, const QString &key, bool useTerminal, bool isForced)
    : IRunConfigurationAspect(runConfig), m_useTerminal(useTerminal),
      m_isForced(isForced), m_checkBox(0), m_key(key)
{
    setDisplayName(tr("Terminal"));
    setId("TerminalAspect");
}

IRunConfigurationAspect *TerminalAspect::create(RunConfiguration *runConfig) const
{
    return new TerminalAspect(runConfig, m_key, false, false);
}

IRunConfigurationAspect *TerminalAspect::clone(RunConfiguration *runConfig) const
{
    return new TerminalAspect(runConfig, m_key, m_useTerminal, m_isForced);
}

void TerminalAspect::addToMainConfigurationWidget(QWidget *parent, QFormLayout *layout)
{
    QTC_CHECK(!m_checkBox);
    m_checkBox = new QCheckBox(tr("Run in terminal"), parent);
    m_checkBox->setChecked(m_useTerminal);
    layout->addRow(QString(), m_checkBox);
    connect(m_checkBox.data(), &QAbstractButton::clicked, this, [this] {
        m_isForced = true;
        setUseTerminal(true);
    });
}

void TerminalAspect::fromMap(const QVariantMap &map)
{
    if (map.contains(m_key)) {
        m_useTerminal = map.value(m_key).toBool();
        m_isForced = true;
    } else {
        m_isForced = false;
    }
}

void TerminalAspect::toMap(QVariantMap &data) const
{
    if (m_isForced)
        data.insert(m_key, m_useTerminal);
}

bool TerminalAspect::useTerminal() const
{
    return m_useTerminal;
}

void TerminalAspect::setUseTerminal(bool useTerminal)
{
    if (m_useTerminal != useTerminal) {
        m_useTerminal = useTerminal;
        emit useTerminalChanged(useTerminal);
    }
}

/*!
    \class ProjectExplorer::WorkingDirectoryAspect
*/

WorkingDirectoryAspect::WorkingDirectoryAspect(RunConfiguration *runConfig, const QString &key, const QString &dir)
    : IRunConfigurationAspect(runConfig), m_workingDirectory(dir), m_chooser(0), m_key(key)
{
    setDisplayName(tr("Working Directory"));
    setId("WorkingDirectoryAspect");
}

IRunConfigurationAspect *WorkingDirectoryAspect::create(RunConfiguration *runConfig) const
{
    return new WorkingDirectoryAspect(runConfig, m_key);
}

IRunConfigurationAspect *WorkingDirectoryAspect::clone(RunConfiguration *runConfig) const
{
    return new WorkingDirectoryAspect(runConfig, m_key, m_workingDirectory);
}

void WorkingDirectoryAspect::addToMainConfigurationWidget(QWidget *parent, QFormLayout *layout)
{
    QTC_CHECK(!m_chooser);
    m_chooser = new PathChooser(parent);
    m_chooser->setHistoryCompleter(m_key);
    m_chooser->setExpectedKind(Utils::PathChooser::Directory);
    m_chooser->setPromptDialogTitle(tr("Select Working Directory"));
    connect(m_chooser, &PathChooser::pathChanged, this, &WorkingDirectoryAspect::setWorkingDirectory);

    auto resetButton = new QToolButton(parent);
    resetButton->setToolTip(tr("Reset to default"));
    resetButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_RESET)));
    connect(resetButton, &QAbstractButton::clicked, this, [this] { m_chooser->setPath(QString()); });

    if (auto envAspect = runConfiguration()->extraAspect<EnvironmentAspect>()) {
        connect(envAspect, &EnvironmentAspect::environmentChanged, this, [this, envAspect] {
            m_chooser->setEnvironment(envAspect->environment());
        });
        m_chooser->setEnvironment(envAspect->environment());
    }

    auto hbox = new QHBoxLayout;
    hbox->addWidget(m_chooser);
    hbox->addWidget(resetButton);
    layout->addRow(tr("Working directory:"), hbox);
}

void WorkingDirectoryAspect::fromMap(const QVariantMap &map)
{
    m_workingDirectory = map.value(m_key).toBool();
}

void WorkingDirectoryAspect::toMap(QVariantMap &data) const
{
    data.insert(m_key, m_workingDirectory);
}

QString WorkingDirectoryAspect::workingDirectory() const
{
    return runConfiguration()->macroExpander()->expandProcessArgs(m_workingDirectory);
}

QString WorkingDirectoryAspect::unexpandedWorkingDirectory() const
{
    return m_workingDirectory;
}

void WorkingDirectoryAspect::setWorkingDirectory(const QString &workingDirectory)
{
    m_workingDirectory = workingDirectory;
}

/*!
    \class ProjectExplorer::ArgumentsAspect
*/

ArgumentsAspect::ArgumentsAspect(RunConfiguration *runConfig, const QString &key, const QString &arguments)
    : IRunConfigurationAspect(runConfig), m_arguments(arguments), m_chooser(0), m_key(key)
{
    setDisplayName(tr("Arguments"));
    setId("ArgumentsAspect");
}

QString ArgumentsAspect::arguments() const
{
    return runConfiguration()->macroExpander()->expandProcessArgs(m_arguments);
}

QString ArgumentsAspect::unexpandedArguments() const
{
    return m_arguments;
}

void ArgumentsAspect::setArguments(const QString &arguments)
{
    m_arguments = arguments;
    if (m_chooser)
        m_chooser->setText(m_arguments);
}

void ArgumentsAspect::fromMap(const QVariantMap &map)
{
    m_arguments = map.value(m_key).toBool();
}

void ArgumentsAspect::toMap(QVariantMap &map) const
{
    map.insert(m_key, m_arguments);
}

IRunConfigurationAspect *ArgumentsAspect::create(RunConfiguration *runConfig) const
{
    return new ArgumentsAspect(runConfig, m_key);
}

IRunConfigurationAspect *ArgumentsAspect::clone(RunConfiguration *runConfig) const
{
    return new ArgumentsAspect(runConfig, m_key, m_arguments);
}

void ArgumentsAspect::addToMainConfigurationWidget(QWidget *parent, QFormLayout *layout)
{
    QTC_CHECK(!m_chooser);
    m_chooser = new FancyLineEdit(parent);
    m_chooser->setHistoryCompleter(m_key);

    connect(m_chooser, &QLineEdit::textChanged, this, &ArgumentsAspect::setArguments);

    layout->addRow(tr("Command line arguments:"), m_chooser);
}

/*!
    \class ProjectExplorer::ExecutableAspect
*/

ExecutableAspect::ExecutableAspect(RunConfiguration *runConfig, const QString &key, const QString &executable)
    : IRunConfigurationAspect(runConfig), m_executable(executable), m_chooser(0), m_key(key)
{
    setDisplayName(tr("Executable"));
    setId("ExecutableAspect");
}

QString ExecutableAspect::executable() const
{
    return runConfiguration()->macroExpander()->expandProcessArgs(m_executable);
}

QString ExecutableAspect::unexpandedExecutable() const
{
    return m_executable;
}

void ExecutableAspect::setExectuable(const QString &executable)
{
    m_executable = executable;
    if (m_chooser)
        m_chooser->setText(m_executable);
}

void ExecutableAspect::fromMap(const QVariantMap &map)
{
    m_executable = map.value(m_key).toBool();
}

void ExecutableAspect::toMap(QVariantMap &map) const
{
    map.insert(m_key, m_executable);
}

IRunConfigurationAspect *ExecutableAspect::create(RunConfiguration *runConfig) const
{
    return new ExecutableAspect(runConfig, m_key);
}

IRunConfigurationAspect *ExecutableAspect::clone(RunConfiguration *runConfig) const
{
    return new ExecutableAspect(runConfig, m_key, m_executable);
}

void ExecutableAspect::addToMainConfigurationWidget(QWidget *parent, QFormLayout *layout)
{
    QTC_CHECK(!m_chooser);
    m_chooser = new FancyLineEdit(parent);
    m_chooser->setHistoryCompleter(m_key);

    connect(m_chooser, &QLineEdit::textChanged, this, &ExecutableAspect::setExectuable);

    layout->addRow(tr("Command line arguments:"), m_chooser);
}

} // namespace ProjectExplorer
<commit_msg>Fix loading project settings<commit_after>/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Contact: http://www.qt.io/licensing
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company.  For licensing terms and
** conditions see http://www.qt.io/terms-conditions.  For further information
** use the contact form at http://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 or version 3 as published by the Free
** Software Foundation and appearing in the file LICENSE.LGPLv21 and
** LICENSE.LGPLv3 included in the packaging of this file.  Please review the
** following information to ensure the GNU Lesser General Public License
** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, The Qt Company gives you certain additional
** rights.  These rights are described in The Qt Company LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "runconfigurationaspects.h"

#include "project.h"
#include "runconfiguration.h"
#include "environmentaspect.h"

#include <coreplugin/coreconstants.h>

#include <utils/fancylineedit.h>
#include <utils/pathchooser.h>

#include <QCheckBox>
#include <QLineEdit>
#include <QDebug>
#include <QFormLayout>
#include <QLabel>
#include <QToolButton>

using namespace Utils;

namespace ProjectExplorer {

/*!
    \class ProjectExplorer::TerminalAspect
*/

TerminalAspect::TerminalAspect(RunConfiguration *runConfig, const QString &key, bool useTerminal, bool isForced)
    : IRunConfigurationAspect(runConfig), m_useTerminal(useTerminal),
      m_isForced(isForced), m_checkBox(0), m_key(key)
{
    setDisplayName(tr("Terminal"));
    setId("TerminalAspect");
}

IRunConfigurationAspect *TerminalAspect::create(RunConfiguration *runConfig) const
{
    return new TerminalAspect(runConfig, m_key, false, false);
}

IRunConfigurationAspect *TerminalAspect::clone(RunConfiguration *runConfig) const
{
    return new TerminalAspect(runConfig, m_key, m_useTerminal, m_isForced);
}

void TerminalAspect::addToMainConfigurationWidget(QWidget *parent, QFormLayout *layout)
{
    QTC_CHECK(!m_checkBox);
    m_checkBox = new QCheckBox(tr("Run in terminal"), parent);
    m_checkBox->setChecked(m_useTerminal);
    layout->addRow(QString(), m_checkBox);
    connect(m_checkBox.data(), &QAbstractButton::clicked, this, [this] {
        m_isForced = true;
        setUseTerminal(true);
    });
}

void TerminalAspect::fromMap(const QVariantMap &map)
{
    if (map.contains(m_key)) {
        m_useTerminal = map.value(m_key).toBool();
        m_isForced = true;
    } else {
        m_isForced = false;
    }
}

void TerminalAspect::toMap(QVariantMap &data) const
{
    if (m_isForced)
        data.insert(m_key, m_useTerminal);
}

bool TerminalAspect::useTerminal() const
{
    return m_useTerminal;
}

void TerminalAspect::setUseTerminal(bool useTerminal)
{
    if (m_useTerminal != useTerminal) {
        m_useTerminal = useTerminal;
        emit useTerminalChanged(useTerminal);
    }
}

/*!
    \class ProjectExplorer::WorkingDirectoryAspect
*/

WorkingDirectoryAspect::WorkingDirectoryAspect(RunConfiguration *runConfig, const QString &key, const QString &dir)
    : IRunConfigurationAspect(runConfig), m_workingDirectory(dir), m_chooser(0), m_key(key)
{
    setDisplayName(tr("Working Directory"));
    setId("WorkingDirectoryAspect");
}

IRunConfigurationAspect *WorkingDirectoryAspect::create(RunConfiguration *runConfig) const
{
    return new WorkingDirectoryAspect(runConfig, m_key);
}

IRunConfigurationAspect *WorkingDirectoryAspect::clone(RunConfiguration *runConfig) const
{
    return new WorkingDirectoryAspect(runConfig, m_key, m_workingDirectory);
}

void WorkingDirectoryAspect::addToMainConfigurationWidget(QWidget *parent, QFormLayout *layout)
{
    QTC_CHECK(!m_chooser);
    m_chooser = new PathChooser(parent);
    m_chooser->setHistoryCompleter(m_key);
    m_chooser->setExpectedKind(Utils::PathChooser::Directory);
    m_chooser->setPromptDialogTitle(tr("Select Working Directory"));
    connect(m_chooser, &PathChooser::pathChanged, this, &WorkingDirectoryAspect::setWorkingDirectory);

    auto resetButton = new QToolButton(parent);
    resetButton->setToolTip(tr("Reset to default"));
    resetButton->setIcon(QIcon(QLatin1String(Core::Constants::ICON_RESET)));
    connect(resetButton, &QAbstractButton::clicked, this, [this] { m_chooser->setPath(QString()); });

    if (auto envAspect = runConfiguration()->extraAspect<EnvironmentAspect>()) {
        connect(envAspect, &EnvironmentAspect::environmentChanged, this, [this, envAspect] {
            m_chooser->setEnvironment(envAspect->environment());
        });
        m_chooser->setEnvironment(envAspect->environment());
    }

    auto hbox = new QHBoxLayout;
    hbox->addWidget(m_chooser);
    hbox->addWidget(resetButton);
    layout->addRow(tr("Working directory:"), hbox);
}

void WorkingDirectoryAspect::fromMap(const QVariantMap &map)
{
    m_workingDirectory = map.value(m_key).toBool();
}

void WorkingDirectoryAspect::toMap(QVariantMap &data) const
{
    data.insert(m_key, m_workingDirectory);
}

QString WorkingDirectoryAspect::workingDirectory() const
{
    return runConfiguration()->macroExpander()->expandProcessArgs(m_workingDirectory);
}

QString WorkingDirectoryAspect::unexpandedWorkingDirectory() const
{
    return m_workingDirectory;
}

void WorkingDirectoryAspect::setWorkingDirectory(const QString &workingDirectory)
{
    m_workingDirectory = workingDirectory;
}

/*!
    \class ProjectExplorer::ArgumentsAspect
*/

ArgumentsAspect::ArgumentsAspect(RunConfiguration *runConfig, const QString &key, const QString &arguments)
    : IRunConfigurationAspect(runConfig), m_arguments(arguments), m_chooser(0), m_key(key)
{
    setDisplayName(tr("Arguments"));
    setId("ArgumentsAspect");
}

QString ArgumentsAspect::arguments() const
{
    return runConfiguration()->macroExpander()->expandProcessArgs(m_arguments);
}

QString ArgumentsAspect::unexpandedArguments() const
{
    return m_arguments;
}

void ArgumentsAspect::setArguments(const QString &arguments)
{
    m_arguments = arguments;
    if (m_chooser)
        m_chooser->setText(m_arguments);
}

void ArgumentsAspect::fromMap(const QVariantMap &map)
{
    m_arguments = map.value(m_key).toString();
}

void ArgumentsAspect::toMap(QVariantMap &map) const
{
    map.insert(m_key, m_arguments);
}

IRunConfigurationAspect *ArgumentsAspect::create(RunConfiguration *runConfig) const
{
    return new ArgumentsAspect(runConfig, m_key);
}

IRunConfigurationAspect *ArgumentsAspect::clone(RunConfiguration *runConfig) const
{
    return new ArgumentsAspect(runConfig, m_key, m_arguments);
}

void ArgumentsAspect::addToMainConfigurationWidget(QWidget *parent, QFormLayout *layout)
{
    QTC_CHECK(!m_chooser);
    m_chooser = new FancyLineEdit(parent);
    m_chooser->setHistoryCompleter(m_key);

    connect(m_chooser, &QLineEdit::textChanged, this, &ArgumentsAspect::setArguments);

    layout->addRow(tr("Command line arguments:"), m_chooser);
}

/*!
    \class ProjectExplorer::ExecutableAspect
*/

ExecutableAspect::ExecutableAspect(RunConfiguration *runConfig, const QString &key, const QString &executable)
    : IRunConfigurationAspect(runConfig), m_executable(executable), m_chooser(0), m_key(key)
{
    setDisplayName(tr("Executable"));
    setId("ExecutableAspect");
}

QString ExecutableAspect::executable() const
{
    return runConfiguration()->macroExpander()->expandProcessArgs(m_executable);
}

QString ExecutableAspect::unexpandedExecutable() const
{
    return m_executable;
}

void ExecutableAspect::setExectuable(const QString &executable)
{
    m_executable = executable;
    if (m_chooser)
        m_chooser->setText(m_executable);
}

void ExecutableAspect::fromMap(const QVariantMap &map)
{
    m_executable = map.value(m_key).toBool();
}

void ExecutableAspect::toMap(QVariantMap &map) const
{
    map.insert(m_key, m_executable);
}

IRunConfigurationAspect *ExecutableAspect::create(RunConfiguration *runConfig) const
{
    return new ExecutableAspect(runConfig, m_key);
}

IRunConfigurationAspect *ExecutableAspect::clone(RunConfiguration *runConfig) const
{
    return new ExecutableAspect(runConfig, m_key, m_executable);
}

void ExecutableAspect::addToMainConfigurationWidget(QWidget *parent, QFormLayout *layout)
{
    QTC_CHECK(!m_chooser);
    m_chooser = new FancyLineEdit(parent);
    m_chooser->setHistoryCompleter(m_key);

    connect(m_chooser, &QLineEdit::textChanged, this, &ExecutableAspect::setExectuable);

    layout->addRow(tr("Command line arguments:"), m_chooser);
}

} // namespace ProjectExplorer
<|endoftext|>


<commit_before>#include <wendy/ConditionVariable.hpp>

namespace wendy {

#ifdef WIN32
ConditionVariable::ConditionVariable(CRITICAL_SECTION *criticalSection)
{
	this->criticalSection = criticalSection;
	this->event = CreateEvent(NULL, FALSE, FALSE, NULL);
}
#else
ConditionVariable::ConditionVariable(pthread_mutex_t *posixMutex)
{
	this->posixMutex = posixMutex;
	pthread_cond_init(&this->posixCondition, NULL);
}
#endif

ConditionVariable::~ConditionVariable()
{
#	ifdef WIN32
		CloseHandle(this->event);
#	else
		pthread_cond_destroy(&this->positionCondition);
#	endif
}

void ConditionVariable::wait()
{
#	ifdef _WIN32
		LeaveCriticalSection(this->criticalSection);
		WaitForSingleObject(this->event, INFINITE);
		EnterCriticalSection(this->criticalSection);
#	else
		pthread_cond_wait(&this->posixCondition, this->posixMutex);
#	endif
}

void ConditionVariable::signal()
{
#	ifdef _WIN32
		SetEvent(this->event);
#	else
		pthread_cond_signal(&this->posixCondition);
#	endif
}

} // wendy namespace

<commit_msg>fixed typo in posix condition variables<commit_after>#include <wendy/ConditionVariable.hpp>

namespace wendy {

#ifdef WIN32
ConditionVariable::ConditionVariable(CRITICAL_SECTION *criticalSection)
{
	this->criticalSection = criticalSection;
	this->event = CreateEvent(NULL, FALSE, FALSE, NULL);
}
#else
ConditionVariable::ConditionVariable(pthread_mutex_t *posixMutex)
{
	this->posixMutex = posixMutex;
	pthread_cond_init(&this->posixCondition, NULL);
}
#endif

ConditionVariable::~ConditionVariable()
{
#	ifdef WIN32
		CloseHandle(this->event);
#	else
		pthread_cond_destroy(&this->posixCondition);
#	endif
}

void ConditionVariable::wait()
{
#	ifdef _WIN32
		LeaveCriticalSection(this->criticalSection);
		WaitForSingleObject(this->event, INFINITE);
		EnterCriticalSection(this->criticalSection);
#	else
		pthread_cond_wait(&this->posixCondition, this->posixMutex);
#	endif
}

void ConditionVariable::signal()
{
#	ifdef _WIN32
		SetEvent(this->event);
#	else
		pthread_cond_signal(&this->posixCondition);
#	endif
}

} // wendy namespace

<|endoftext|>


<commit_before>#ifndef BFC_COMBINE_SET_VISITOR_HPP
#define BFC_COMBINE_SET_VISITOR_HPP

#include "ast/mod.hpp"
#include "test_visitor.hpp"
#include "opt_seq_base_visitor.hpp"
#include "types.h"

namespace bfc {
namespace ast {

class combine_set_visitor : public opt_seq_base_visitor {

public:

    status visit(set &node) {
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            test_combine_set_visitor v;
            if (opt_seq.back().accept(v) == CONTINUE) {
                // discard the previous node (undone by this set)
                opt_seq.pop_back();
            }
        }
        // copy the node
        return opt_seq_base_visitor::handle_set(node);
    }

    status visit(const set &node) {
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            test_combine_set_visitor v;
            if (opt_seq.back().accept(v) == CONTINUE) {
                // discard the previous node (undone by this set)
                opt_seq.pop_back();
            }
        }
        // copy the node
        return opt_seq_base_visitor::handle_set(node);
    }

    status visit(add &node) {
        // discard any zero value node
        if (node.value() == 0) {
            return CONTINUE;
        }
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            try_combine_set_inc_visitor v(node.offset(), node.value(), true);
            if (opt_seq.back().accept(v) == CONTINUE) {
                opt_seq.pop_back();
                opt_seq.emplace_back(new set(node.loc(), node.offset(), v.new_value()));
                return CONTINUE;
            }
        }
        // else make node copy
        return opt_seq_base_visitor::handle_add(node);
    }

    status visit(const add &node) {
        // discard any zero value node
        if (node.value() == 0) {
            return CONTINUE;
        }
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            try_combine_set_inc_visitor v(node.offset(), node.value(), true);
            if (opt_seq.back().accept(v) == CONTINUE) {
                opt_seq.pop_back();
                opt_seq.emplace_back(new set(node.loc(), node.offset(), v.new_value()));
                return CONTINUE;
            }
        }
        // else make node copy
        return opt_seq_base_visitor::handle_add(node);
    }

    status visit(sub &node) {
        // discard any zero value node
        if (node.value() == 0) {
            return CONTINUE;
        }
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            try_combine_set_inc_visitor v(node.offset(), node.value(), false);
            if (opt_seq.back().accept(v) == CONTINUE) {
                opt_seq.pop_back();
                opt_seq.emplace_back(new set(node.loc(), node.offset(), v.new_value()));
                return CONTINUE;
            }
        }
        // else make node copy
        return opt_seq_base_visitor::handle_sub(node);
    }

    status visit(const sub &node) {
        // discard any zero value node
        if (node.value() == 0) {
            return CONTINUE;
        }
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            try_combine_set_inc_visitor v(node.offset(), node.value(), false);
            if (opt_seq.back().accept(v) == CONTINUE) {
                opt_seq.pop_back();
                opt_seq.emplace_back(new set(node.loc(), node.offset(), v.new_value()));
                return CONTINUE;
            }
        }
        // else make node copy
        return opt_seq_base_visitor::handle_sub(node);
    }

private:

    class test_combine_set_visitor : public test_visitor {

        public:

            status visit(set &node) { return CONTINUE; }

            status visit(const add &set) { return CONTINUE; }

            status visit(add &node) { return CONTINUE; }

            status visit(const add &node) { return CONTINUE; }

            status visit(sub &node) { return CONTINUE; }

            status visit(const sub &node) { return CONTINUE; }

    };

    class try_combine_set_inc_visitor : public test_visitor {

        public:
            try_combine_inc_visitor(ptrdiff_t offset, bf_value val, bool isAdd) :
                isAdd(isAdd), next_off(offset),  next_val(val) {}

            bf_value new_value() {
                return new_val;
            }

            status visit(set &node) {
                if (node.offset() != next_off) {
                    return BREAK;
                }
                new_val = node.value();
                isAdd ? new_val += next_val : new_val -= next_val;
                return CONTINUE;
            }

            status visit(const set &node) {
                if (node.offset() != next_off) {
                    return BREAK;
                }
                new_val = node.value();
                isAdd ? new_val += next_val : new_val -= next_val;
                return CONTINUE;
            }

        private:
            bool isAdd;
            ptrdiff_t next_off;
            bf_value next_val;
            bf_value new_val;
    };

};

}
}

#endif /* !BFC_COMBINE_SET_VISITOR_HPP */
<commit_msg>Typo yo<commit_after>#ifndef BFC_COMBINE_SET_VISITOR_HPP
#define BFC_COMBINE_SET_VISITOR_HPP

#include "ast/mod.hpp"
#include "test_visitor.hpp"
#include "opt_seq_base_visitor.hpp"
#include "types.h"

namespace bfc {
namespace ast {

class combine_set_visitor : public opt_seq_base_visitor {

public:

    status visit(set &node) {
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            test_combine_set_visitor v;
            if (opt_seq.back().accept(v) == CONTINUE) {
                // discard the previous node (undone by this set)
                opt_seq.pop_back();
            }
        }
        // copy the node
        return opt_seq_base_visitor::handle_set(node);
    }

    status visit(const set &node) {
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            test_combine_set_visitor v;
            if (opt_seq.back().accept(v) == CONTINUE) {
                // discard the previous node (undone by this set)
                opt_seq.pop_back();
            }
        }
        // copy the node
        return opt_seq_base_visitor::handle_set(node);
    }

    status visit(add &node) {
        // discard any zero value node
        if (node.value() == 0) {
            return CONTINUE;
        }
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            try_combine_set_inc_visitor v(node.offset(), node.value(), true);
            if (opt_seq.back().accept(v) == CONTINUE) {
                opt_seq.pop_back();
                opt_seq.emplace_back(new set(node.loc(), node.offset(), v.new_value()));
                return CONTINUE;
            }
        }
        // else make node copy
        return opt_seq_base_visitor::handle_add(node);
    }

    status visit(const add &node) {
        // discard any zero value node
        if (node.value() == 0) {
            return CONTINUE;
        }
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            try_combine_set_inc_visitor v(node.offset(), node.value(), true);
            if (opt_seq.back().accept(v) == CONTINUE) {
                opt_seq.pop_back();
                opt_seq.emplace_back(new set(node.loc(), node.offset(), v.new_value()));
                return CONTINUE;
            }
        }
        // else make node copy
        return opt_seq_base_visitor::handle_add(node);
    }

    status visit(sub &node) {
        // discard any zero value node
        if (node.value() == 0) {
            return CONTINUE;
        }
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            try_combine_set_inc_visitor v(node.offset(), node.value(), false);
            if (opt_seq.back().accept(v) == CONTINUE) {
                opt_seq.pop_back();
                opt_seq.emplace_back(new set(node.loc(), node.offset(), v.new_value()));
                return CONTINUE;
            }
        }
        // else make node copy
        return opt_seq_base_visitor::handle_sub(node);
    }

    status visit(const sub &node) {
        // discard any zero value node
        if (node.value() == 0) {
            return CONTINUE;
        }
        // Only attempt to combine if there is a previous node
        if (!opt_seq.empty()) {
            // try to combine with the previous node if possible
            try_combine_set_inc_visitor v(node.offset(), node.value(), false);
            if (opt_seq.back().accept(v) == CONTINUE) {
                opt_seq.pop_back();
                opt_seq.emplace_back(new set(node.loc(), node.offset(), v.new_value()));
                return CONTINUE;
            }
        }
        // else make node copy
        return opt_seq_base_visitor::handle_sub(node);
    }

private:

    class test_combine_set_visitor : public test_visitor {

        public:

            status visit(set &node) { return CONTINUE; }

            status visit(const set &node) { return CONTINUE; }

            status visit(add &node) { return CONTINUE; }

            status visit(const add &node) { return CONTINUE; }

            status visit(sub &node) { return CONTINUE; }

            status visit(const sub &node) { return CONTINUE; }

    };

    class try_combine_set_inc_visitor : public test_visitor {

        public:
            try_combine_inc_visitor(ptrdiff_t offset, bf_value val, bool isAdd) :
                isAdd(isAdd), next_off(offset),  next_val(val) {}

            bf_value new_value() {
                return new_val;
            }

            status visit(set &node) {
                if (node.offset() != next_off) {
                    return BREAK;
                }
                new_val = node.value();
                isAdd ? new_val += next_val : new_val -= next_val;
                return CONTINUE;
            }

            status visit(const set &node) {
                if (node.offset() != next_off) {
                    return BREAK;
                }
                new_val = node.value();
                isAdd ? new_val += next_val : new_val -= next_val;
                return CONTINUE;
            }

        private:
            bool isAdd;
            ptrdiff_t next_off;
            bf_value next_val;
            bf_value new_val;
    };

};

}
}

#endif /* !BFC_COMBINE_SET_VISITOR_HPP */
<|endoftext|>


<commit_before>// This file is part of OpenMVG, an Open Multiple View Geometry C++ library.

// Copyright (c) 2019 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "openMVG/cameras/Camera_Pinhole.hpp"
#include "openMVG/cameras/Camera_Spherical.hpp"
#include "openMVG/geometry/pose3.hpp"
#include "openMVG/image/image_io.hpp"
#include "openMVG/image/sample.hpp"
#include "openMVG/numeric/eigen_alias_definition.hpp"
#include "openMVG/sfm/sfm_data.hpp"
#include "openMVG/sfm/sfm_data_io.hpp"
#include "openMVG/sfm/sfm_landmark.hpp"
#include "openMVG/sfm/sfm_view.hpp"
#include "openMVG/types.hpp"

#include "third_party/cmdLine/cmdLine.h"
#include "third_party/progress/progress_display.hpp"
#include "third_party/stlplus3/filesystemSimplified/file_system.hpp"

#include <array>
#include <cstdlib>
#include <cmath>
#include <iomanip>

using namespace openMVG;
using namespace openMVG::cameras;
using namespace openMVG::geometry;
using namespace openMVG::image;
using namespace openMVG::sfm;

/// Compute a rectilinear camera focal for a given angular desired FoV and image size
double FocalFromPinholeHeight
(
 int h,
 double thetaMax = openMVG::D2R(60) // Camera FoV
)
{
    float f = 1.f;
    while ( thetaMax < atan2( h / (2 * f) , 1))
    {
        ++f;
    }
    return f;
}

const std::array<openMVG::Mat3,6> GetCubicRotations()
{
    using namespace openMVG;
    return {
        RotationAroundY(D2R(0)),    // front
        RotationAroundY(D2R(-90)),   // right
        RotationAroundY(D2R(-180)),  // behind
        RotationAroundY(D2R(-270)),  // left
        RotationAroundX(D2R(-90)),   // up
        RotationAroundX(D2R(+90))   // down
    };
}

void ComputeCubicCameraIntrinsics(const int cubic_image_size,
                                  openMVG::cameras::Pinhole_Intrinsic & pinhole_camera)
{
    const double focal = FocalFromPinholeHeight(cubic_image_size, D2R(45));
    const double principal_point_xy = cubic_image_size / 2;
    pinhole_camera = Pinhole_Intrinsic(cubic_image_size,
                                       cubic_image_size,
                                       focal,
                                       principal_point_xy,
                                       principal_point_xy);
}

template <typename ImageT>
void SphericalToCubic
(
 const ImageT & equirectangular_image,
 const openMVG::cameras::Pinhole_Intrinsic & pinhole_camera,
 std::vector<ImageT> & cube_images
 )
{
    using namespace openMVG;
    using namespace openMVG::cameras;

    const image::Sampler2d<image::SamplerLinear> sampler;

    //
    // Initialize a camera model for each image domain
    // - the equirectangular panorama
    const Intrinsic_Spherical sphere_camera(
                                            equirectangular_image.Width() - 1, equirectangular_image.Height() - 1);
    // - the cube faces
    //
    // Perform backward/inverse rendering:
    // - For each cube face (rotation)
    // - Sample the panorama pixel by camera to camera bearing vector projection
    const int cubic_image_size = pinhole_camera.h();
    cube_images.resize(6, ImageT(cubic_image_size, cubic_image_size));

    // Initialize the rotation matrices corresponding to each cube face
    const std::array<Mat3, 6> rot_matrix = GetCubicRotations();

    for (const int i_rot : {0, 1, 2, 3, 4, 5})
    {
        // std::cout << "generate view " << i_rot << std::endl;
        auto & pinhole_image = cube_images[i_rot];
        const int image_width = pinhole_image.Width();
        const int image_height = pinhole_image.Height();

        // For every pinhole image pixels
        for (int x = 0; x < image_width; ++x)
        {
            // std::cout << "   row = " << x << std::endl;
            for (int y = 0; y < image_height; ++y)
            { // Project the pinhole bearing vector to the spherical camera
                const Vec3 pinhole_bearing = rot_matrix[i_rot].transpose() * pinhole_camera(Vec2(x, y));
                const Vec2 sphere_proj = sphere_camera.project(pinhole_bearing);

                if (equirectangular_image.Contains(sphere_proj(1), sphere_proj(0)))
                {
                    pinhole_image(y, x) = sampler(equirectangular_image, sphere_proj(1), sphere_proj(0));
                }
            }
        }
    }
}

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

    CmdLine cmd;
    std::string s_sfm_data_filename;
    std::string s_out_dir = "";
    int force_recompute_images = 1;

    cmd.add( make_option('i', s_sfm_data_filename, "sfmdata") );
    cmd.add( make_option('o', s_out_dir, "outdir") );
    cmd.add( make_option('f', force_recompute_images, "force_compute_cubic_images") );

    try {
        if (argc == 1) throw std::string("Invalid command line parameter.");
        cmd.process(argc, argv);
    } catch (const std::string& s) {
        std::cerr << "Usage: " << argv[0] << '\n'
        << "[-i|--sfmdata] filename, the SfM_Data file to convert\n"
        << "[-o|--outdir path]\n"
        << "[-f|--force_recompute_images] (default 1)\n"
        << std::endl;

        std::cerr << s << std::endl;
        return EXIT_FAILURE;
    }

    std::cout << "force_recompute_images = " << force_recompute_images << std::endl;

    // Create output dir
    if (!stlplus::folder_exists(s_out_dir))
        stlplus::folder_create(s_out_dir);

    SfM_Data sfm_data;
    if (!Load(sfm_data, s_sfm_data_filename, ESfM_Data(ALL))) {
        std::cerr << std::endl
        << "The input SfM_Data file \""<< s_sfm_data_filename << "\" cannot be read." << std::endl;
        return EXIT_FAILURE;
    }

    SfM_Data sfm_data_out; // the sfm_data that stores the cubical image list

    std::vector<image::Image<image::RGBColor>> cube_images;
    // Convert every spherical view to cubic views
    {
        std::cout << "Generating cubic views:";
        C_Progress_display my_progress_bar(sfm_data.GetViews().size());
        const Views & views = sfm_data.GetViews();
        const Poses & poses = sfm_data.GetPoses();
        const Landmarks & structure = sfm_data.GetLandmarks();

        // generate views and camera poses for each new views
        for (int i = 0; i < static_cast<int>(views.size()); ++i)
        {
            ++my_progress_bar;
            auto view_it = views.begin();
            std::advance(view_it, i);
            const View * view = view_it->second.get();
            if (!sfm_data.IsPoseAndIntrinsicDefined(view))
                continue;

            Intrinsics::const_iterator iter_intrinsic = sfm_data.GetIntrinsics().find(view->id_intrinsic);

            const IntrinsicBase * cam = iter_intrinsic->second.get();
            if (cam && cam->getType() == CAMERA_SPHERICAL)
            {
                // We have a valid view with a corresponding camera & pose
                //std::cout << "sfm_data.s_root_path = " << sfm_data.s_root_path << std::endl;
                //std::cout << "view->s_Img_path = "     << view->s_Img_path << std::endl;
                const std::string view_path = stlplus::create_filespec(sfm_data.s_root_path, view->s_Img_path);
                image::Image<image::RGBColor> spherical_image;
                if (!ReadImage(view_path.c_str(), &spherical_image))
                {
                    std::cerr << "Cannot read the input panoramic image: " << view_path << std::endl;
                    return EXIT_FAILURE;
                }

                openMVG::cameras::Pinhole_Intrinsic pinhole_camera;
                const int cubic_image_size = 1024;
                ComputeCubicCameraIntrinsics(cubic_image_size, pinhole_camera);

                // when cubical image computation is needed
                if (force_recompute_images)
                    SphericalToCubic(spherical_image, pinhole_camera, cube_images);

                const std::array<Mat3,6> rot_matrix = GetCubicRotations();

                for (const int cubic_image_id : {0,1,2,3,4,5})
                {
                    std::ostringstream os;
                    os << std::setw(8) << std::setfill('0') << cubic_image_id;
                    const std::string dst_cube_image = stlplus::create_filespec(
                                                                                stlplus::folder_append_separator(s_out_dir),
                                                                                stlplus::basename_part(view_path)
                                                                                + "_perspective_"
                                                                                + os.str(),
                                                                                "png"
                                                                                );
                    // when cubical image computation is needed
                    if (force_recompute_images)
                    {
                        if (!WriteImage(dst_cube_image.c_str(), cube_images[cubic_image_id]))
                        {
                            std::cout << "Cannot export cubic images to: " << dst_cube_image << std::endl;
                            return EXIT_FAILURE;
                        }
                    }

                    const View v(
                                 dst_cube_image,
                                 view->id_view * 6 + cubic_image_id, // Id view
                                 0,  // Id intrinsic
                                 view->id_pose * 6 + cubic_image_id,  // Id pose
                                 pinhole_camera.w(),
                                 pinhole_camera.h()
                                 );
                    sfm_data_out.views[v.id_view] = std::make_shared<View>(v);

                    // due to 360 cameras, rotation after BA might come with determinant -1
                    // if so, negate the rotation for future use.
                    Mat3 tmp_rotation = poses.at(view->id_pose).rotation();
                    if (tmp_rotation.determinant()<0)
                        tmp_rotation = tmp_rotation*(-1.0f);

                    sfm_data_out.poses[v.id_pose] =
                    Pose3(
                          rot_matrix[cubic_image_id] * tmp_rotation,
                          poses.at(view->id_pose).center()
                          );

                    if (sfm_data_out.GetIntrinsics().count(v.id_intrinsic) == 0)
                        sfm_data_out.intrinsics[v.id_intrinsic] =
                        std::make_shared<Pinhole_Intrinsic>(pinhole_camera);
                }
            }
        } // end of generate views and camera poses for each new views

        // output camera views for debugging purpose
        if (0)
        {
            const int num_output_views = sfm_data_out.views.size();
            std::cout << "num of output views = " << num_output_views << std::endl;
            for (int i = 0; i < num_output_views; ++i) {
                const Pose3 pose = sfm_data_out.poses[i];
                std::cout << "R{" << i+1 << "} = [" << pose.rotation()(0,0) << " " << pose.rotation()(0,1) << " " << pose.rotation()(0,2) << std::endl
                                                   << pose.rotation()(1,0) << " " << pose.rotation()(1,1) << " " << pose.rotation()(1,2) << std::endl
                                                   << pose.rotation()(2,0) << " " << pose.rotation()(2,1) << " " << pose.rotation()(2,2) << "]';" << std::endl;
                std::cout << "T{" << i+1 << "} = [" << pose.center().x() << " " << pose.center().y() << " " << pose.center().z() << "]';" << std::endl;
            }
        }

        // generate structure and associate it with new camera views
        {
            std::cout << "Creating cubic sfm_data structure:";

            C_Progress_display my_progress_bar(structure.size());
            for (Landmarks::const_iterator it = structure.begin(); it != structure.end(); ++it) {
                // std::cout << it->second.X.x() << ", " << it->second.X.y() << ", " << it->second.X.z() << std::endl;
                ++my_progress_bar;

                const Observations & obs = it->second.obs;
                Observations::const_iterator itObs = obs.begin();

                Landmark out_landmark;
                out_landmark.X = it->second.X;

                // iterate across 360 views that can see the point
                while (itObs != obs.end())
                {
                    IndexT pano_view_key = itObs->first;
                    IndexT feature_key = itObs->second.id_feat;

                    // get cubical camera ids and poses and reproject to see if the 3D point is inside the view
                    bool is_reprojection_found = false;
                    for (IndexT local_view_index = pano_view_key * 6; local_view_index < pano_view_key * 6 + 6; ++local_view_index)
                    {
                        IndexT intrinsic_id = sfm_data_out.views[local_view_index]->id_intrinsic;
                        IndexT extrinsic_id = sfm_data_out.views[local_view_index]->id_pose;
                        const Pose3 pose = sfm_data_out.poses[extrinsic_id];
                        const Mat34 P = sfm_data_out.intrinsics[intrinsic_id]->get_projective_equivalent(pose);

                        const int image_height = sfm_data_out.intrinsics[intrinsic_id]->h();
                        const int image_width  = sfm_data_out.intrinsics[intrinsic_id]->w();
                        Vec2 projection = Project(P, it->second.X);

                        if (projection.x() < 0 || projection.x() >= image_width || projection.y() < 0 || projection.y() >= image_height)
                            continue;

                        Vec3 point_to_cam_dir = it->second.X - pose.center();
                        point_to_cam_dir.normalize();
                        Vec3 cam_looking_dir = pose.rotation().transpose() * Vec3(0,0, 1);
                        cam_looking_dir.normalize();

                        const double angle = acos(point_to_cam_dir.dot(cam_looking_dir))/M_PI*180;

                        if (angle < 0 || angle > 90)
                            continue;
                        // std::cout << "view " << local_view_index << " has angle = " << angle << std::endl;
                        out_landmark.obs[local_view_index] = Observation(projection, feature_key);
                        is_reprojection_found = true;
                        break; // if one of the 6 views observe the 3D point, no other views from the 6 views should observe it
                    } // end of looping 6 view of 1 pano image

                    assert(is_reprojection_found); // make sure the observation is found
                    ++itObs;
                } // end of observations from all panos
                sfm_data_out.structure.insert({it->first, out_landmark});
            }
        }
    } // end of converting spherical view to cubical
    if (!Save(
              sfm_data_out,
              stlplus::create_filespec(
                                       stlplus::folder_append_separator(s_out_dir),
                                       "sfm_data_perspective.bin"),
              ESfM_Data(ALL))) {
        std::cerr << std::endl
        << "Cannot save the output sfm_data file" << std::endl;
        return EXIT_FAILURE;
    }

    std::cout
    << " #views: " << sfm_data_out.views.size() << "\n"
    << " #poses: " << sfm_data_out.poses.size() << "\n"
    << " #intrinsics: " << sfm_data_out.intrinsics.size() << "\n"
    << " #tracks: " << sfm_data_out.structure.size() << "\n" << std::endl;

    // Exit program
    return EXIT_SUCCESS;
}

<commit_msg>[SfM/export] Update openMVGSpherical2Cubic #1505<commit_after>// This file is part of OpenMVG, an Open Multiple View Geometry C++ library.

// Copyright (c) 2019 Pierre MOULON.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "openMVG/cameras/Camera_Pinhole.hpp"
#include "openMVG/cameras/Camera_Spherical.hpp"
#include "openMVG/geometry/pose3.hpp"
#include "openMVG/image/image_io.hpp"
#include "openMVG/image/sample.hpp"
#include "openMVG/numeric/eigen_alias_definition.hpp"
#include "openMVG/sfm/sfm_data.hpp"
#include "openMVG/sfm/sfm_data_io.hpp"
#include "openMVG/sfm/sfm_landmark.hpp"
#include "openMVG/sfm/sfm_view.hpp"
#include "openMVG/types.hpp"

#include "third_party/cmdLine/cmdLine.h"
#include "third_party/progress/progress_display.hpp"
#include "third_party/stlplus3/filesystemSimplified/file_system.hpp"

#include <array>
#include <cstdlib>
#include <cmath>
#include <iomanip>

using namespace openMVG;
using namespace openMVG::cameras;
using namespace openMVG::geometry;
using namespace openMVG::image;
using namespace openMVG::sfm;

/// Compute a rectilinear camera focal for a given angular desired FoV and image size
double FocalFromPinholeHeight
(
  int h,
  double thetaMax = openMVG::D2R(60) // Camera FoV
)
{
  float f = 1.f;
  while ( thetaMax < atan2( h / (2 * f) , 1))
  {
    ++f;
  }
  return f;
}

const std::array<openMVG::Mat3,6> GetCubicRotations()
{
  using namespace openMVG;
  return {
    RotationAroundY(D2R(0)),     // front
    RotationAroundY(D2R(-90)),   // right
    RotationAroundY(D2R(-180)),  // behind
    RotationAroundY(D2R(-270)),  // left
    RotationAroundX(D2R(-90)),   // up
    RotationAroundX(D2R(+90))    // down
  };
}

void ComputeCubicCameraIntrinsics(const int cubic_image_size,
                                  openMVG::cameras::Pinhole_Intrinsic & pinhole_camera)
{
  const double focal = FocalFromPinholeHeight(cubic_image_size, D2R(45));
  const double principal_point_xy = cubic_image_size / 2;
  pinhole_camera = Pinhole_Intrinsic(cubic_image_size,
                                     cubic_image_size,
                                     focal,
                                     principal_point_xy,
                                     principal_point_xy);
}

template <typename ImageT>
void SphericalToCubic
(
  const ImageT & equirectangular_image,
  const openMVG::cameras::Pinhole_Intrinsic & pinhole_camera,
  std::vector<ImageT> & cube_images
)
{
  using namespace openMVG;
  using namespace openMVG::cameras;

  const image::Sampler2d<image::SamplerLinear> sampler;

  //
  // Initialize a camera model for each image domain
  // - the equirectangular panorama
  const Intrinsic_Spherical sphere_camera(equirectangular_image.Width()  - 1,
                                          equirectangular_image.Height() - 1);
  // - the cube faces
  //
  // Perform backward/inverse rendering:
  // - For each cube face (rotation)
  // - Sample the panorama pixel by camera to camera bearing vector projection
  const int cubic_image_size = pinhole_camera.h();
  cube_images.resize(6, ImageT(cubic_image_size, cubic_image_size));

  // Initialize the rotation matrices corresponding to each cube face
  const std::array<Mat3, 6> rot_matrix = GetCubicRotations();

  for (const int i_rot : {0, 1, 2, 3, 4, 5})
  {
    auto & pinhole_image = cube_images[i_rot];
    const int image_width = pinhole_image.Width();
    const int image_height = pinhole_image.Height();

    // For every pinhole image pixels
    for (int x = 0; x < image_width; ++x)
    {
      for (int y = 0; y < image_height; ++y)
      { // Project the pinhole bearing vector to the spherical camera
        const Vec3 pinhole_bearing = rot_matrix[i_rot].transpose() * pinhole_camera(Vec2(x, y));
        const Vec2 sphere_proj = sphere_camera.project(pinhole_bearing);

        if (equirectangular_image.Contains(sphere_proj(1), sphere_proj(0)))
        {
          pinhole_image(y, x) = sampler(equirectangular_image, sphere_proj(1), sphere_proj(0));
        }
      }
    }
  }
}

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

  CmdLine cmd;
  std::string s_sfm_data_filename;
  std::string s_out_dir = "";
  int force_recompute_images = 1;

  cmd.add( make_option('i', s_sfm_data_filename, "sfmdata") );
  cmd.add( make_option('o', s_out_dir, "outdir") );
  cmd.add( make_option('f', force_recompute_images, "force_compute_cubic_images") );

  try {
      if (argc == 1) throw std::string("Invalid command line parameter.");
      cmd.process(argc, argv);
  } catch (const std::string& s) {
      std::cerr << "Usage: " << argv[0] << '\n'
      << "[-i|--sfmdata] filename, the SfM_Data file to convert\n"
      << "[-o|--outdir path]\n"
      << "[-f|--force_recompute_images] (default 1)\n"
      << std::endl;

      std::cerr << s << std::endl;
      return EXIT_FAILURE;
  }

  std::cout << "force_recompute_images = " << force_recompute_images << std::endl;

  // Create output dir
  if (!stlplus::folder_exists(s_out_dir))
      stlplus::folder_create(s_out_dir);

  SfM_Data sfm_data;
  if (!Load(sfm_data, s_sfm_data_filename, ESfM_Data(ALL))) {
      std::cerr << std::endl
      << "The input SfM_Data file \""<< s_sfm_data_filename << "\" cannot be read." << std::endl;
      return EXIT_FAILURE;
  }

  SfM_Data sfm_data_out; // the sfm_data that stores the cubical image list
  sfm_data_out.s_root_path = s_out_dir;

  // Convert every spherical view to cubic views
  {
    std::cout << "Generating cubic views:";
    C_Progress_display my_progress_bar(sfm_data.GetViews().size());
    const Views & views = sfm_data.GetViews();
    const Poses & poses = sfm_data.GetPoses();
    const Landmarks & structure = sfm_data.GetLandmarks();

    // generate views and camera poses for each new views
    int error_status = 0;
    #pragma omp parallel for shared(error_status) if(error_status < 1)
    for (int i = 0; i < static_cast<int>(views.size()); ++i)
    {
      ++my_progress_bar;
      auto view_it = views.begin();
      std::advance(view_it, i);
      const View * view = view_it->second.get();
      if (!sfm_data.IsPoseAndIntrinsicDefined(view))
          continue;

      Intrinsics::const_iterator iter_intrinsic = sfm_data.GetIntrinsics().find(view->id_intrinsic);

      const IntrinsicBase * cam = iter_intrinsic->second.get();
      if (cam && cam->getType() == CAMERA_SPHERICAL)
      {
        // We have a valid view with a corresponding camera & pose
        const std::string view_path = stlplus::create_filespec(sfm_data.s_root_path, view->s_Img_path);
        image::Image<image::RGBColor> spherical_image;
        if (!ReadImage(view_path.c_str(), &spherical_image))
        {
          std::cerr << "Cannot read the input panoramic image: " << view_path << std::endl;
          #pragma omp atomic
          ++error_status;
          continue;
        }

        openMVG::cameras::Pinhole_Intrinsic pinhole_camera;
        const int cubic_image_size = 1024;
        ComputeCubicCameraIntrinsics(cubic_image_size, pinhole_camera);

        // when cubical image computation is needed
        std::vector<image::Image<image::RGBColor>> cube_images;
        if (force_recompute_images)
          SphericalToCubic(spherical_image, pinhole_camera, cube_images);

        const std::array<Mat3,6> rot_matrix = GetCubicRotations();

        for (const int cubic_image_id : {0,1,2,3,4,5})
        {
          std::ostringstream os;
          os << std::setw(8) << std::setfill('0') << cubic_image_id;
          const std::string dst_cube_image = stlplus::create_filespec(
            stlplus::folder_append_separator(s_out_dir),
            stlplus::basename_part(view_path)
            + "_perspective_"
            + os.str(),
            "png");
          // when cubical image computation is needed
          if (force_recompute_images)
          {
            if (!WriteImage(dst_cube_image.c_str(), cube_images[cubic_image_id]))
            {
              std::cout << "Cannot export cubic images to: " << dst_cube_image << std::endl;
              #pragma omp atomic
              ++error_status;
              continue;
            }
          }

          const View v(
            stlplus::filename_part(dst_cube_image),
            view->id_view * 6 + cubic_image_id, // Id view
            0,  // Id intrinsic
            view->id_pose * 6 + cubic_image_id,  // Id pose
            pinhole_camera.w(),
            pinhole_camera.h());
          sfm_data_out.views[v.id_view] = std::make_shared<View>(v);

          // due to 360 cameras, rotation after BA might come with determinant -1
          // if so, negate the rotation for future use.
          Mat3 tmp_rotation = poses.at(view->id_pose).rotation();
          if (tmp_rotation.determinant() < 0)
          {
            std::cout << "Negative determinant" << std::endl;
            tmp_rotation = tmp_rotation*(-1.0f);
          }

          sfm_data_out.poses[v.id_pose] =
            Pose3(rot_matrix[cubic_image_id] * tmp_rotation,
                  poses.at(view->id_pose).center());

          if (sfm_data_out.GetIntrinsics().count(v.id_intrinsic) == 0)
            sfm_data_out.intrinsics[v.id_intrinsic] =
              std::make_shared<Pinhole_Intrinsic>(pinhole_camera);
      }
    }
    else
    {
      std::cout << "Loaded scene does not have spherical camera" << std::endl;
      #pragma omp atomic
      ++error_status;
      continue;
    }
  } // end of generate views and camera poses for each new views

  if (error_status > 0) // early exit
    return EXIT_FAILURE;

  // generate structure and associate it with new camera views
  {
    std::cout << "Creating cubic sfm_data structure:";

    C_Progress_display my_progress_bar(structure.size());
    for (const auto & it_structure : structure)
    {
      ++my_progress_bar;

      const Observations & obs = it_structure.second.obs;

      Landmark out_landmark;
      out_landmark.X = it_structure.second.X;

      // iterate across 360 views that can see the point
      for(const auto & it_obs : obs)
      {
        const IndexT pano_view_key = it_obs.first;
        const IndexT feature_key   = it_obs.second.id_feat;

        // get cubical camera ids and poses and reproject to see if the 3D point is inside the view
        bool is_reprojection_found = false;
        for (IndexT local_view_index = pano_view_key * 6; local_view_index < pano_view_key * 6 + 6; ++local_view_index)
        {
          const IndexT intrinsic_id = sfm_data_out.views[local_view_index]->id_intrinsic;
          const IndexT extrinsic_id = sfm_data_out.views[local_view_index]->id_pose;
          const Pose3 pose = sfm_data_out.poses[extrinsic_id];
          const auto cam = sfm_data_out.intrinsics[intrinsic_id];

          const int image_height = cam->h();
          const int image_width  = cam->w();

          const Vec2 projection = cam->project(pose(it_structure.second.X));

          if (projection.x() < 0 || projection.x() >= image_width ||
              projection.y() < 0 || projection.y() >= image_height)
              continue;

          const Vec3 point_to_cam_dir = (it_structure.second.X - pose.center()).normalized();
          const Vec3 cam_looking_dir = (pose.rotation().transpose() * Vec3(0, 0, 1)).normalized();

          const double angle = R2D(acos(point_to_cam_dir.dot(cam_looking_dir)));

          if (angle < 0 || angle > 90)
            continue;

          out_landmark.obs[local_view_index] = Observation(projection, feature_key);
          is_reprojection_found = true;
          break; // if one of the 6 views observe the 3D point, no other views from the 6 views should observe it
        } // end of looping 6 view of 1 pano image

        assert(is_reprojection_found); // make sure the observation is found
      } // end of observations from all panos
      sfm_data_out.structure.insert({it_structure.first, out_landmark});
    }
  }

  } // end of converting spherical view to cubical

  if (!Save(sfm_data_out,
            stlplus::create_filespec(stlplus::folder_append_separator(s_out_dir),
                                     "sfm_data_perspective.bin"),
            ESfM_Data(ALL))) {
    std::cerr << std::endl
    << "Cannot save the output sfm_data file" << std::endl;
    return EXIT_FAILURE;
  }

  std::cout
    << " #views: " << sfm_data_out.views.size() << "\n"
    << " #poses: " << sfm_data_out.poses.size() << "\n"
    << " #intrinsics: " << sfm_data_out.intrinsics.size() << "\n"
    << " #tracks: " << sfm_data_out.structure.size() << "\n" << std::endl;

  // Exit program
  return EXIT_SUCCESS;
}
<|endoftext|>