<commit_before>/*
 * Copyright (C) 2009, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */
/**
 ** \file object/system-class.cc
 ** \brief Creation of the URBI object system.
 */

#include <ltdl.h>

//#define ENABLE_DEBUG_TRACES
#include <libport/compiler.hh>
#include <libport/cstdlib>
#include <libport/format.hh>
#include <libport/program-name.hh>
#include <libport/xltdl.hh>

#include <cerrno>
#include <memory>
#include <sstream>

#include <kernel/uconnection.hh>
#include <kernel/uobject.hh>
#include <kernel/userver.hh>

#include <object/code.hh>
#include <object/cxx-primitive.hh>
#include <object/dictionary.hh>
#include <object/float.hh>
#include <object/global.hh>
#include <object/list.hh>
#include <object/lobby.hh>
#include <object/path.hh>
#include <object/symbols.hh>
#include <object/system.hh>
#include <object/tag.hh>
#include <object/task.hh>
#include <parser/transform.hh>
#include <runner/at-handler.hh>
#include <runner/interpreter.hh>
#include <runner/raise.hh>
#include <runner/runner.hh>

#include <ast/nary.hh>
#include <ast/routine.hh>

namespace object
{
  using kernel::urbiserver;

  static inline
  runner::Runner&
  runner()
  {
    return ::kernel::urbiserver->getCurrentRunner();
  }

  static inline
  runner::Interpreter&
  interpreter()
  {
    return dynamic_cast<runner::Interpreter&>(runner());
  }

  static inline
  sched::Scheduler&
  scheduler()
  {
    return runner().scheduler_get();
  }

  // Extract a filename from a String or a Path object
  static std::string
  filename_get(const rObject& o)
  {
    if (o.is_a<Path>())
      return o->as<Path>()->as_string();
    type_check<String>(o);
    return o->as<String>()->value_get();
  }

  rObject
  execute_parsed(parser::parse_result_type p,
                 libport::Symbol fun, std::string e)
  {
    runner::Interpreter& run = interpreter();

    // Report potential errors
    {
      ast::rNary errs = new ast::Nary();
      p->process_errors(*errs);
      run(errs.get());
    }

    ast::rConstAst ast = parser::transform(p->ast_get());
    if (!ast)
      RAISE(e);

    runner::Interpreter* sub = new runner::Interpreter(run, ast, fun);
    // So that it will resist to the call to yield_until_terminated,
    // and will be reclaimed at the end of the scope.
    sched::rJob job = sub;
    sched::Job::ChildrenCollecter children(&run, 1);
    run.register_child(sub, children);
    sub->start_job();
    try
    {
      run.yield_until_terminated(*job);
    }
    catch (const sched::ChildException& ce)
    {
      // Kill the sub-job and propagate.
      ce.rethrow_child_exception();
    }
    return sub->result_get();
  }

  rObject system_class;

  /*--------------------.
  | System primitives.  |
  `--------------------*/

#define SERVER_FUNCTION(Function)               \
  static void                                   \
  system_ ## Function()                         \
  {                                             \
    urbiserver->Function();                     \
  }

  SERVER_FUNCTION(reboot)
  SERVER_FUNCTION(shutdown)

#undef SERVER_FUNCTION

  static void
  system_sleep(const rObject&, libport::ufloat seconds)
  {
    runner::Runner& r = runner();
    if (seconds == std::numeric_limits<ufloat>::infinity())
      r.yield_until_terminated(r);
    else
      r.yield_until(r.scheduler_get().get_time()
                    + static_cast<libport::utime_t>(seconds * 1000000.0));
  }

  static float
  system_time()
  {
    return scheduler().get_time() / 1000000.0;
  }

  static float
  system_shiftedTime()
  {
    runner::Runner& r = runner();
    return (r.scheduler_get().get_time() - r.time_shift_get()) / 1000000.0;
  }

  static rObject
  system_eval(const rObject&, const std::string& code)
  {
    return execute_parsed(parser::parse(code, ast::loc()),
                          SYMBOL(eval),
                          "error executing command: " + code);
  }

  static void
  system_registerAtJob(const rObject&,
                       const rObject& condition,
                       const rObject& clause,
                       const rObject& on_leave)
  {
    runner::register_at_job(interpreter(),
			    condition, clause, on_leave);
  }

  static rObject
  system_scopeTag()
  {
    return new Tag(interpreter().scope_tag());
  }

  static rObject
  system_searchFile(const rObject&, const rObject& f)
  {
    const std::string& filename = filename_get(f);
    try
    {
      return new Path(urbiserver->find_file(filename));
    }
    catch (libport::file_library::Not_found&)
    {
      runner::raise_urbi(SYMBOL(FileNotFound), to_urbi(filename));
      // Never reached
      assertion(false);
      return 0;
    }
  }

  static List::value_type
  system_searchPath()
  {
    List::value_type res;
    foreach (const libport::path& p, urbiserver->search_path.search_path_get())
      res.push_back(new Path(p));
    return res;
  }

  static rObject
  system_loadFile(const rObject&, const rObject& f)
  {
    const std::string& filename = filename_get(f);
#if defined ENABLE_SERIALIZATION
    if (!libport::path(filename).exists())
      runner::raise_urbi(SYMBOL(FileNotFound), to_urbi(filename));
#endif
    return execute_parsed(parser::parse_file(filename),
                          SYMBOL(loadFile),
                          "error loading file: " + filename);
  }

  static rObject
  system_currentRunner()
  {
    return runner().as_task();
  }

  static float
  system_cycle()
  {
    return scheduler().cycle_get();
  }

  static libport::Symbol
  system_fresh()
  {
    return libport::Symbol::fresh();
  }

  static rObject
  system_lobby()
  {
    return runner().lobby_get();
  }

  static void
  system_nonInterruptible()
  {
    runner().non_interruptible_set(true);
  }

  static void
  system_quit()
  {
    runner().lobby_get()->connection_get().close();
  }

  static void
  system_spawn(const rObject&,
	       const rCode& code,
               const rObject& clear_tags)
  {
    runner::Runner& r = runner();
    runner::Interpreter* new_runner =
      new runner::Interpreter(interpreter(),
                              rObject(code),
                              libport::Symbol::fresh(r.name_get()));

    if (clear_tags->as_bool())
      new_runner->tag_stack_clear();

    new_runner->time_shift_set(r.time_shift_get());
    new_runner->start_job();
  }

  static rObject
  system_stats()
  {
    const sched::scheduler_stats_type& stats = scheduler().stats_get();

    // If statistics have just been reset, return "nil" since we cannot
    // return anything significant.
    if (stats.empty())
      return nil_class;

    // The space after "Symbol(" is mandatory to avoid triggering an error in
    // symbol generation code
    Dictionary::value_type res;
#define ADDSTAT(Suffix, Function, Divisor)      \
    res[libport::Symbol("cycles" # Suffix)] =   \
      new Float(stats.Function() / Divisor)
    ADDSTAT(, size, 1);
    ADDSTAT(Max, max, 1e6);
    ADDSTAT(Mean, mean, 1e6);
    ADDSTAT(Min, min, 1e6);
    ADDSTAT(StdDev, standard_deviation, 1e6);
    ADDSTAT(Variance, variance, 1e3);
#undef ADDSTAT
    return new Dictionary(res);
  }

  static void
  system_resetStats()
  {
    scheduler().stats_reset();
  }

  // This should give a backtrace as an urbi object.
  static void
  system_backtrace()
  {
    // FIXME: This method sucks a bit, because show_backtrace sucks a
    // bit, because our channeling/message-sending system sucks a lot.
    runner::Runner::backtrace_type bt = runner().backtrace_get();
    bt.pop_back();
    rforeach (const runner::Runner::frame_type& elt, bt)
      runner().send_message("backtrace", elt.name + " (" + elt.location + ")");
  }

  static List::value_type
  system_jobs()
  {
    List::value_type res;
    foreach(sched::rJob job, scheduler().jobs_get())
      res.push_back(dynamic_cast<runner::Runner*>(job.get())->as_task());
    return res;
  }

  static int
  system_aliveJobs()
  {
    return sched::Job::alive_jobs();
  }

  static void
  system_breakpoint()
  {
    return;
  }

#define SERVER_SET_VAR(Function, Variable, Value)       \
  static void                                           \
  system_ ## Function ()                                \
  {                                                     \
    urbiserver->Variable = Value;                       \
  }

  SERVER_SET_VAR(stopall, stopall, true)

#undef SERVER_SET_VAR

  static rObject
  system_getenv(const rObject&, const std::string& name)
  {
    char* res = getenv(name.c_str());
    return res ? new String(res) : nil_class;
  }

  static rObject
  system_setenv(const rObject&, const std::string& name, rObject value)
  {
    rString v = value->call(SYMBOL(asString))->as<String>();
    setenv(name.c_str(), v->value_get().c_str(), 1);
    return v;
  }

  static rObject
  system_unsetenv(const rObject&, const std::string& name)
  {
    rObject res = system_getenv(0, name);
    unsetenv(name.c_str());
    return res;
  }

  static libport::InstanceTracker<Lobby>::set_type
  system_lobbies()
  {
    return Lobby::instances_get();
  }

  static void
  load(const rObject& name, bool global)
  {
    const std::string& filename = filename_get(name);

    libport::xlt_advise dl;
    dl.ext().global(global).path()
      .push_back(libport::xgetenv("URBI_UOBJECT_PATH", ".:"), ":");

    libport::xlt_handle handle = dl.open(filename);
    if (!handle.handle)
      RAISE("Failed to open `" + filename + "': " + lt_dlerror());
    handle.detach();

    // Reload uobjects
    uobjects_reload();

    // Reload CxxObjects
    CxxObject::create();
    CxxObject::initialize(global_class);
    CxxObject::cleanup();
  }

  static void
  system_loadLibrary(const rObject&, const rObject& name)
  {
    load(name, true);
  }

  static void
  system_loadModule(const rObject&, const rObject& name)
  {
   load(name, false);
  }

  static libport::cli_args_type urbi_arguments_;
  static boost::optional<std::string> urbi_program_name_;

  void
  system_push_argument(const std::string& arg)
  {
    urbi_arguments_.push_back(arg);
  }

  void
  system_set_program_name(const std::string& name)
  {
    urbi_program_name_ = name;
  }

  static const libport::cli_args_type&
  system_arguments()
  {
    return urbi_arguments_;
  }

  static boost::optional<std::string>
  system_programName()
  {
    return urbi_program_name_;
  }

  static void
  system__exit(const rObject&, int status)
  {
    exit(status);
  }

  static int
  system_system(const rObject&, const std::string& s)
  {
    int res = system(s.c_str());
    switch (res)
    {
    case -1:
      // FIXME: This is potentially widly used, see also path.cc.
      RAISE(libport::format("%1%: %2%", strerror(errno), s));
      break;
    case 127:
      RAISE(libport::format("shell failed: %1%", s));
      break;
    }
    return res;
  }

  void
  system_class_initialize()
  {
#define DECLARE(Name)                                                   \
    system_class->slot_set(SYMBOL(Name),                                \
                           make_primitive(&system_##Name))              \

    DECLARE(_exit);
    DECLARE(aliveJobs);
    DECLARE(arguments);
    DECLARE(backtrace);
    DECLARE(breakpoint);
    DECLARE(currentRunner);
    DECLARE(cycle);
    DECLARE(eval);
    DECLARE(fresh);
    DECLARE(getenv);
    DECLARE(jobs);
    DECLARE(loadFile);
    DECLARE(loadModule);
    DECLARE(loadLibrary);
    DECLARE(lobbies);
    DECLARE(lobby);
    DECLARE(nonInterruptible);
    DECLARE(programName);
    DECLARE(quit);
    DECLARE(reboot);
    DECLARE(registerAtJob);
    DECLARE(resetStats);
    DECLARE(scopeTag);
    DECLARE(searchFile);
    DECLARE(searchPath);
    DECLARE(setenv);
    DECLARE(shiftedTime);
    DECLARE(shutdown);
    DECLARE(sleep);
    DECLARE(spawn);
    DECLARE(stats);
    DECLARE(stopall);
    DECLARE(system);
    DECLARE(time);
    DECLARE(unsetenv);

#undef DECLARE
  }

} // namespace object
<commit_msg>include changes.<commit_after>/*
 * Copyright (C) 2009, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */
/**
 ** \file object/system-class.cc
 ** \brief Creation of the URBI object system.
 */

//#define ENABLE_DEBUG_TRACES
#include <libport/compiler.hh>
#include <libport/cstdlib>
#include <libport/format.hh>
#include <libport/program-name.hh>
#include <libport/xltdl.hh>

#include <cerrno>
#include <memory>
#include <sstream>

#include <kernel/uconnection.hh>
#include <kernel/uobject.hh>
#include <kernel/userver.hh>

#include <object/code.hh>
#include <object/cxx-primitive.hh>
#include <object/dictionary.hh>
#include <object/float.hh>
#include <object/global.hh>
#include <object/list.hh>
#include <object/lobby.hh>
#include <object/path.hh>
#include <object/symbols.hh>
#include <object/system.hh>
#include <object/tag.hh>
#include <object/task.hh>
#include <parser/transform.hh>
#include <runner/at-handler.hh>
#include <runner/interpreter.hh>
#include <runner/raise.hh>
#include <runner/runner.hh>

#include <ast/nary.hh>
#include <ast/routine.hh>

namespace object
{
  using kernel::urbiserver;

  static inline
  runner::Runner&
  runner()
  {
    return ::kernel::urbiserver->getCurrentRunner();
  }

  static inline
  runner::Interpreter&
  interpreter()
  {
    return dynamic_cast<runner::Interpreter&>(runner());
  }

  static inline
  sched::Scheduler&
  scheduler()
  {
    return runner().scheduler_get();
  }

  // Extract a filename from a String or a Path object
  static std::string
  filename_get(const rObject& o)
  {
    if (o.is_a<Path>())
      return o->as<Path>()->as_string();
    type_check<String>(o);
    return o->as<String>()->value_get();
  }

  rObject
  execute_parsed(parser::parse_result_type p,
                 libport::Symbol fun, std::string e)
  {
    runner::Interpreter& run = interpreter();

    // Report potential errors
    {
      ast::rNary errs = new ast::Nary();
      p->process_errors(*errs);
      run(errs.get());
    }

    ast::rConstAst ast = parser::transform(p->ast_get());
    if (!ast)
      RAISE(e);

    runner::Interpreter* sub = new runner::Interpreter(run, ast, fun);
    // So that it will resist to the call to yield_until_terminated,
    // and will be reclaimed at the end of the scope.
    sched::rJob job = sub;
    sched::Job::ChildrenCollecter children(&run, 1);
    run.register_child(sub, children);
    sub->start_job();
    try
    {
      run.yield_until_terminated(*job);
    }
    catch (const sched::ChildException& ce)
    {
      // Kill the sub-job and propagate.
      ce.rethrow_child_exception();
    }
    return sub->result_get();
  }

  rObject system_class;

  /*--------------------.
  | System primitives.  |
  `--------------------*/

#define SERVER_FUNCTION(Function)               \
  static void                                   \
  system_ ## Function()                         \
  {                                             \
    urbiserver->Function();                     \
  }

  SERVER_FUNCTION(reboot)
  SERVER_FUNCTION(shutdown)

#undef SERVER_FUNCTION

  static void
  system_sleep(const rObject&, libport::ufloat seconds)
  {
    runner::Runner& r = runner();
    if (seconds == std::numeric_limits<ufloat>::infinity())
      r.yield_until_terminated(r);
    else
      r.yield_until(r.scheduler_get().get_time()
                    + static_cast<libport::utime_t>(seconds * 1000000.0));
  }

  static float
  system_time()
  {
    return scheduler().get_time() / 1000000.0;
  }

  static float
  system_shiftedTime()
  {
    runner::Runner& r = runner();
    return (r.scheduler_get().get_time() - r.time_shift_get()) / 1000000.0;
  }

  static rObject
  system_eval(const rObject&, const std::string& code)
  {
    return execute_parsed(parser::parse(code, ast::loc()),
                          SYMBOL(eval),
                          "error executing command: " + code);
  }

  static void
  system_registerAtJob(const rObject&,
                       const rObject& condition,
                       const rObject& clause,
                       const rObject& on_leave)
  {
    runner::register_at_job(interpreter(),
			    condition, clause, on_leave);
  }

  static rObject
  system_scopeTag()
  {
    return new Tag(interpreter().scope_tag());
  }

  static rObject
  system_searchFile(const rObject&, const rObject& f)
  {
    const std::string& filename = filename_get(f);
    try
    {
      return new Path(urbiserver->find_file(filename));
    }
    catch (libport::file_library::Not_found&)
    {
      runner::raise_urbi(SYMBOL(FileNotFound), to_urbi(filename));
      // Never reached
      assertion(false);
      return 0;
    }
  }

  static List::value_type
  system_searchPath()
  {
    List::value_type res;
    foreach (const libport::path& p, urbiserver->search_path.search_path_get())
      res.push_back(new Path(p));
    return res;
  }

  static rObject
  system_loadFile(const rObject&, const rObject& f)
  {
    const std::string& filename = filename_get(f);
#if defined ENABLE_SERIALIZATION
    if (!libport::path(filename).exists())
      runner::raise_urbi(SYMBOL(FileNotFound), to_urbi(filename));
#endif
    return execute_parsed(parser::parse_file(filename),
                          SYMBOL(loadFile),
                          "error loading file: " + filename);
  }

  static rObject
  system_currentRunner()
  {
    return runner().as_task();
  }

  static float
  system_cycle()
  {
    return scheduler().cycle_get();
  }

  static libport::Symbol
  system_fresh()
  {
    return libport::Symbol::fresh();
  }

  static rObject
  system_lobby()
  {
    return runner().lobby_get();
  }

  static void
  system_nonInterruptible()
  {
    runner().non_interruptible_set(true);
  }

  static void
  system_quit()
  {
    runner().lobby_get()->connection_get().close();
  }

  static void
  system_spawn(const rObject&,
	       const rCode& code,
               const rObject& clear_tags)
  {
    runner::Runner& r = runner();
    runner::Interpreter* new_runner =
      new runner::Interpreter(interpreter(),
                              rObject(code),
                              libport::Symbol::fresh(r.name_get()));

    if (clear_tags->as_bool())
      new_runner->tag_stack_clear();

    new_runner->time_shift_set(r.time_shift_get());
    new_runner->start_job();
  }

  static rObject
  system_stats()
  {
    const sched::scheduler_stats_type& stats = scheduler().stats_get();

    // If statistics have just been reset, return "nil" since we cannot
    // return anything significant.
    if (stats.empty())
      return nil_class;

    // The space after "Symbol(" is mandatory to avoid triggering an error in
    // symbol generation code
    Dictionary::value_type res;
#define ADDSTAT(Suffix, Function, Divisor)      \
    res[libport::Symbol("cycles" # Suffix)] =   \
      new Float(stats.Function() / Divisor)
    ADDSTAT(, size, 1);
    ADDSTAT(Max, max, 1e6);
    ADDSTAT(Mean, mean, 1e6);
    ADDSTAT(Min, min, 1e6);
    ADDSTAT(StdDev, standard_deviation, 1e6);
    ADDSTAT(Variance, variance, 1e3);
#undef ADDSTAT
    return new Dictionary(res);
  }

  static void
  system_resetStats()
  {
    scheduler().stats_reset();
  }

  // This should give a backtrace as an urbi object.
  static void
  system_backtrace()
  {
    // FIXME: This method sucks a bit, because show_backtrace sucks a
    // bit, because our channeling/message-sending system sucks a lot.
    runner::Runner::backtrace_type bt = runner().backtrace_get();
    bt.pop_back();
    rforeach (const runner::Runner::frame_type& elt, bt)
      runner().send_message("backtrace", elt.name + " (" + elt.location + ")");
  }

  static List::value_type
  system_jobs()
  {
    List::value_type res;
    foreach(sched::rJob job, scheduler().jobs_get())
      res.push_back(dynamic_cast<runner::Runner*>(job.get())->as_task());
    return res;
  }

  static int
  system_aliveJobs()
  {
    return sched::Job::alive_jobs();
  }

  static void
  system_breakpoint()
  {
    return;
  }

#define SERVER_SET_VAR(Function, Variable, Value)       \
  static void                                           \
  system_ ## Function ()                                \
  {                                                     \
    urbiserver->Variable = Value;                       \
  }

  SERVER_SET_VAR(stopall, stopall, true)

#undef SERVER_SET_VAR

  static rObject
  system_getenv(const rObject&, const std::string& name)
  {
    char* res = getenv(name.c_str());
    return res ? new String(res) : nil_class;
  }

  static rObject
  system_setenv(const rObject&, const std::string& name, rObject value)
  {
    rString v = value->call(SYMBOL(asString))->as<String>();
    setenv(name.c_str(), v->value_get().c_str(), 1);
    return v;
  }

  static rObject
  system_unsetenv(const rObject&, const std::string& name)
  {
    rObject res = system_getenv(0, name);
    unsetenv(name.c_str());
    return res;
  }

  static libport::InstanceTracker<Lobby>::set_type
  system_lobbies()
  {
    return Lobby::instances_get();
  }

  static void
  load(const rObject& name, bool global)
  {
    const std::string& filename = filename_get(name);

    libport::xlt_advise dl;
    dl.ext().global(global).path()
      .push_back(libport::xgetenv("URBI_UOBJECT_PATH", ".:"), ":");

    libport::xlt_handle handle = dl.open(filename);
    if (!handle.handle)
      RAISE("Failed to open `" + filename + "': " + lt_dlerror());
    handle.detach();

    // Reload uobjects
    uobjects_reload();

    // Reload CxxObjects
    CxxObject::create();
    CxxObject::initialize(global_class);
    CxxObject::cleanup();
  }

  static void
  system_loadLibrary(const rObject&, const rObject& name)
  {
    load(name, true);
  }

  static void
  system_loadModule(const rObject&, const rObject& name)
  {
   load(name, false);
  }

  static libport::cli_args_type urbi_arguments_;
  static boost::optional<std::string> urbi_program_name_;

  void
  system_push_argument(const std::string& arg)
  {
    urbi_arguments_.push_back(arg);
  }

  void
  system_set_program_name(const std::string& name)
  {
    urbi_program_name_ = name;
  }

  static const libport::cli_args_type&
  system_arguments()
  {
    return urbi_arguments_;
  }

  static boost::optional<std::string>
  system_programName()
  {
    return urbi_program_name_;
  }

  static void
  system__exit(const rObject&, int status)
  {
    exit(status);
  }

  static int
  system_system(const rObject&, const std::string& s)
  {
    int res = system(s.c_str());
    switch (res)
    {
    case -1:
      // FIXME: This is potentially widly used, see also path.cc.
      RAISE(libport::format("%1%: %2%", strerror(errno), s));
      break;
    case 127:
      RAISE(libport::format("shell failed: %1%", s));
      break;
    }
    return res;
  }

  void
  system_class_initialize()
  {
#define DECLARE(Name)                                                   \
    system_class->slot_set(SYMBOL(Name),                                \
                           make_primitive(&system_##Name))              \

    DECLARE(_exit);
    DECLARE(aliveJobs);
    DECLARE(arguments);
    DECLARE(backtrace);
    DECLARE(breakpoint);
    DECLARE(currentRunner);
    DECLARE(cycle);
    DECLARE(eval);
    DECLARE(fresh);
    DECLARE(getenv);
    DECLARE(jobs);
    DECLARE(loadFile);
    DECLARE(loadModule);
    DECLARE(loadLibrary);
    DECLARE(lobbies);
    DECLARE(lobby);
    DECLARE(nonInterruptible);
    DECLARE(programName);
    DECLARE(quit);
    DECLARE(reboot);
    DECLARE(registerAtJob);
    DECLARE(resetStats);
    DECLARE(scopeTag);
    DECLARE(searchFile);
    DECLARE(searchPath);
    DECLARE(setenv);
    DECLARE(shiftedTime);
    DECLARE(shutdown);
    DECLARE(sleep);
    DECLARE(spawn);
    DECLARE(stats);
    DECLARE(stopall);
    DECLARE(system);
    DECLARE(time);
    DECLARE(unsetenv);

#undef DECLARE
  }

} // namespace object
<|endoftext|>


<commit_before>#include <coffee/graphics/apis/gleam/renderer/gleamrenderer.h>
#include <coffee/core/coffee_strings.h>
#include <coffee/core/platform_data.h>

#include <coffee/graphics/apis/gleam/gleam.h>
#include <coffee/core/CProfiling>

#if !defined(COFFEE_GLEAM_DESKTOP) && !defined(COFFEE_USE_MAEMO_EGL)
#include <SDL_video.h>
#else
#include <EGL/egl.h>
#endif

#include "conversion.h"

namespace Coffee{
namespace Display{

using GL = CGL::CGL_Implementation;

GLeamRenderer::GLeamRenderer(GLApplication *app):
    GLLoader(app)
{
}

GLeamRenderer::~GLeamRenderer()
{
}

#if !defined(COFFEE_ONLY_GLES20)
void gleamcallback(GLenum src, GLenum type,GLuint id,GLenum sev,GLsizei,const GLchar* msg,
                   const void* param)
{
    const GLeamRenderer* renderer = (const GLeamRenderer*)param;
    CGL::CGDbgMsg cmsg;
#ifdef COFFEE_GLEAM_DESKTOP
    cmsg.sev = gl_convertsev(sev);
    cmsg.type = gl_converttype(type);
    cmsg.comp = gl_convertcomp(src);
#endif
    cmsg.id = id;
    cmsg.msg = msg;
    renderer->bindingCallback(&cmsg);
}
#endif

void GLeamRenderer::bindingCallback(const void *report) const
{
    const CGL::CGDbgMsg* msg =
            (const CGL::CGDbgMsg*)report;
    cBasicPrint("GL:{0}:{1}:{2}:{3}: {4}",
                msg->comp,msg->sev,msg->type,
                msg->id,msg->msg.c_str());
}

bool GLeamRenderer::bindingPreInit(const GLProperties&,CString*)
{
    return true;
}

bool GLeamRenderer::bindingInit(const GLProperties&,CString*)
{
    return true;
}

bool GLeamRenderer::bindingPostInit(const GLProperties& p, CString *err)
{
    Profiler::PushContext("GLeam");

    cVerbose(8, "Acquiring GL context from {0}, {1}", (u64)m_app, (u64)m_app->glContext());

    m_app->glContext()->acquireContext();

    Profiler::Profile("Context acquisition");

    bool status = false;

    cDebug("Attempting to load version: {0}",p.version);

#if !defined(COFFEE_GLEAM_DESKTOP)

#if !defined(COFFEE_USE_MAEMO_EGL)
    GLADloadproc procload = SDL_GL_GetProcAddress;
#else
    GLADloadproc procload = (GLADloadproc)eglGetProcAddress;
#endif

#endif

    if(!(p.flags & GLProperties::Flags::GLES))
    {
#ifdef COFFEE_GLEAM_DESKTOP
        const static CGLVersion v33(3,3);
        const static CGLVersion v43(4,3);
        const static CGLVersion v45(4,5);

        if(p.version>=v45)
        {
//            cDebug("Loading context version: GL {0}",(_cbasic_version<uint8> const&)v45);
            status = CGL::CGL45::LoadBinding(m_app->glContext());
        }else if(p.version>=v43)
        {
//            cDebug("Loading context version: GL {0}",(_cbasic_version<uint8> const&)v43);
            status = CGL::CGL43::LoadBinding(m_app->glContext());
        } else if(p.version>=v33)
        {
//            cDebug("Loading context version: GL {0}",(_cbasic_version<uint8> const&)v33);
            status = CGL::CGL33::LoadBinding(m_app->glContext());
        }
#endif
    }else{
#ifndef COFFEE_GLEAM_DESKTOP
        const static CGLVersion v20es(2,0);
#if !defined(COFFEE_ONLY_GLES20)
        const static CGLVersion v30es(3,0);
        const static CGLVersion v32es(3,2);
#endif

#if !defined(COFFEE_ONLY_GLES20)
        if(p.version>=v32es)
        {
            status = CGL::CGLES32::LoadBinding(m_app->glContext(),procload);
        }else
        if(p.version==v30es)
        {
            status = CGL::CGLES30::LoadBinding(m_app->glContext(),procload);
        }else
#endif
        if(p.version==v20es)
        {
#if !defined(COFFEE_LINKED_GLES)
            status = CGL::CGLES20::LoadBinding(m_app->glContext(),procload);
#else
            cVerbose(7, "Checking OpenGL ES 2.0 functions...");
            status = CGL::CGLES20::LoadBinding(m_app->glContext(),nullptr);
#endif
        }
#endif
    }

    Profiler::Profile("Loading GL function pointers");
    cVerbose(7, "Function pointer checks succeeded: {0}", status);

    if(!status)
    {
//        cLog(__FILE__,__LINE__,CFStrings::Graphics_GLeam_Renderer_Name,
//             CFStrings::Graphics_GLeam_Renderer_FailLoad);
        /*Context or graphics card on fire? Just get out!*/
        if(err)
            *err = CFStrings::Graphics_GLeam_Renderer_FailLoad;
        return false;
    }

    cDebug("Rendering device info: {0}",GL::Debug::Renderer());
    if(feval(p.flags&GLProperties::GLCoreProfile))
        cDebug("OpenGL core profile version: {0}",GL::Debug::ContextVersion());
    else
        cDebug("OpenGL (non-core) version: {0}",GL::Debug::ContextVersion());
    cDebug("OpenGL GLSL version: {0}",GL::Debug::ShaderLanguageVersion());

    if(GL::DebuggingSupported())
    {
#if !defined(COFFEE_WINDOWS) && !defined(COFFEE_ONLY_GLES20)
        GL::Debug::SetDebugMode(true);
        GL::Debug::DebugSetCallback(gleamcallback,this);
#endif
    }

    Profiler::Profile("Debug setup");
    return true;
}

void GLeamRenderer::bindingTerminate()
{
    GL::Debug::FreeInternalFormats();
}

}
}
<commit_msg> - Fix problem with GLADloadproc<commit_after>#include <coffee/graphics/apis/gleam/renderer/gleamrenderer.h>
#include <coffee/core/coffee_strings.h>
#include <coffee/core/platform_data.h>

#include <coffee/graphics/apis/gleam/gleam.h>
#include <coffee/core/CProfiling>

#if !defined(COFFEE_GLEAM_DESKTOP) && !defined(COFFEE_USE_MAEMO_EGL)
#include <SDL_video.h>
#else
#include <EGL/egl.h>
#endif

#include "conversion.h"

namespace Coffee{
namespace Display{

using GL = CGL::CGL_Implementation;

GLeamRenderer::GLeamRenderer(GLApplication *app):
    GLLoader(app)
{
}

GLeamRenderer::~GLeamRenderer()
{
}

#if !defined(COFFEE_ONLY_GLES20)
void gleamcallback(GLenum src, GLenum type,GLuint id,GLenum sev,GLsizei,const GLchar* msg,
                   const void* param)
{
    const GLeamRenderer* renderer = (const GLeamRenderer*)param;
    CGL::CGDbgMsg cmsg;
#ifdef COFFEE_GLEAM_DESKTOP
    cmsg.sev = gl_convertsev(sev);
    cmsg.type = gl_converttype(type);
    cmsg.comp = gl_convertcomp(src);
#endif
    cmsg.id = id;
    cmsg.msg = msg;
    renderer->bindingCallback(&cmsg);
}
#endif

void GLeamRenderer::bindingCallback(const void *report) const
{
    const CGL::CGDbgMsg* msg =
            (const CGL::CGDbgMsg*)report;
    cBasicPrint("GL:{0}:{1}:{2}:{3}: {4}",
                msg->comp,msg->sev,msg->type,
                msg->id,msg->msg.c_str());
}

bool GLeamRenderer::bindingPreInit(const GLProperties&,CString*)
{
    return true;
}

bool GLeamRenderer::bindingInit(const GLProperties&,CString*)
{
    return true;
}

bool GLeamRenderer::bindingPostInit(const GLProperties& p, CString *err)
{
    Profiler::PushContext("GLeam");

    cVerbose(8, "Acquiring GL context from {0}, {1}", (u64)m_app, (u64)m_app->glContext());

    m_app->glContext()->acquireContext();

    Profiler::Profile("Context acquisition");

    bool status = false;

    cDebug("Attempting to load version: {0}",p.version);

#if !defined(COFFEE_GLEAM_DESKTOP)

#if !defined(COFFEE_LINKED_GLES)
#if !defined(COFFEE_USE_MAEMO_EGL)
    GLADloadproc procload = SDL_GL_GetProcAddress;
#else
    GLADloadproc procload = (GLADloadproc)eglGetProcAddress;
#endif
#endif

#endif

    if(!(p.flags & GLProperties::Flags::GLES))
    {
#ifdef COFFEE_GLEAM_DESKTOP
        const static CGLVersion v33(3,3);
        const static CGLVersion v43(4,3);
        const static CGLVersion v45(4,5);

        if(p.version>=v45)
        {
//            cDebug("Loading context version: GL {0}",(_cbasic_version<uint8> const&)v45);
            status = CGL::CGL45::LoadBinding(m_app->glContext());
        }else if(p.version>=v43)
        {
//            cDebug("Loading context version: GL {0}",(_cbasic_version<uint8> const&)v43);
            status = CGL::CGL43::LoadBinding(m_app->glContext());
        } else if(p.version>=v33)
        {
//            cDebug("Loading context version: GL {0}",(_cbasic_version<uint8> const&)v33);
            status = CGL::CGL33::LoadBinding(m_app->glContext());
        }
#endif
    }else{
#ifndef COFFEE_GLEAM_DESKTOP
        const static CGLVersion v20es(2,0);
#if !defined(COFFEE_ONLY_GLES20)
        const static CGLVersion v30es(3,0);
        const static CGLVersion v32es(3,2);
#endif

#if !defined(COFFEE_ONLY_GLES20)
        if(p.version>=v32es)
        {
            status = CGL::CGLES32::LoadBinding(m_app->glContext(),procload);
        }else
        if(p.version==v30es)
        {
            status = CGL::CGLES30::LoadBinding(m_app->glContext(),procload);
        }else
#endif
        if(p.version==v20es)
        {
#if !defined(COFFEE_LINKED_GLES)
            status = CGL::CGLES20::LoadBinding(m_app->glContext(),procload);
#else
            cVerbose(7, "Checking OpenGL ES 2.0 functions...");
            status = CGL::CGLES20::LoadBinding(m_app->glContext(),nullptr);
#endif
        }
#endif
    }

    Profiler::Profile("Loading GL function pointers");
    cVerbose(7, "Function pointer checks succeeded: {0}", status);

    if(!status)
    {
//        cLog(__FILE__,__LINE__,CFStrings::Graphics_GLeam_Renderer_Name,
//             CFStrings::Graphics_GLeam_Renderer_FailLoad);
        /*Context or graphics card on fire? Just get out!*/
        if(err)
            *err = CFStrings::Graphics_GLeam_Renderer_FailLoad;
        return false;
    }

    cDebug("Rendering device info: {0}",GL::Debug::Renderer());
    if(feval(p.flags&GLProperties::GLCoreProfile))
        cDebug("OpenGL core profile version: {0}",GL::Debug::ContextVersion());
    else
        cDebug("OpenGL (non-core) version: {0}",GL::Debug::ContextVersion());
    cDebug("OpenGL GLSL version: {0}",GL::Debug::ShaderLanguageVersion());

    if(GL::DebuggingSupported())
    {
#if !defined(COFFEE_WINDOWS) && !defined(COFFEE_ONLY_GLES20)
        GL::Debug::SetDebugMode(true);
        GL::Debug::DebugSetCallback(gleamcallback,this);
#endif
    }

    Profiler::Profile("Debug setup");
    return true;
}

void GLeamRenderer::bindingTerminate()
{
    GL::Debug::FreeInternalFormats();
}

}
}
<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2006 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "Image.h"

#include "DisplayEngine.h"
#include "Player.h"
#include "ISurface.h"

#include "../graphics/Filtercolorize.h"
#include "../graphics/Filterfliprgb.h"

#include "../base/Logger.h"
#include "../base/ScopeTimer.h"
#include "../base/XMLHelper.h"

#include <Magick++.h>

#include <iostream>
#include <sstream>

using namespace std;

namespace avg {

Image::Image ()
    : m_Hue(-1),
      m_Saturation(-1)
{
    m_pBmp = BitmapPtr(new Bitmap(IntPoint(1,1), R8G8B8X8));
}

Image::Image (const xmlNodePtr xmlNode, Player * pPlayer)
    : RasterNode(xmlNode, pPlayer)
{
    m_href = getDefaultedStringAttr (xmlNode, "href", "");
    m_Hue = getDefaultedIntAttr (xmlNode, "hue", -1);
    m_Saturation = getDefaultedIntAttr (xmlNode, "saturation", -1);
    m_pBmp = BitmapPtr(new Bitmap(IntPoint(1,1), R8G8B8X8));
    load();
}

Image::~Image ()
{
}

void Image::setDisplayEngine(DisplayEngine * pEngine)
{
    RasterNode::setDisplayEngine(pEngine);

    setupSurface(&*m_pBmp);
}

void Image::disconnect()
{
/*
    // Commenting this (and the corresponding line in setupSurface) out causes
    // a copy of the image to always be kept in main memory, so no readback has to
    // take place.

    // Unload textures but keep bitmap in memory.
    ISurface * pSurface = getSurface();
    BitmapPtr pSurfaceBmp = pSurface->lockBmp();
    m_pBmp = BitmapPtr(new Bitmap(pSurfaceBmp->getSize(), pSurfaceBmp->getPixelFormat()));
    m_pBmp->copyPixels(*pSurfaceBmp);
    getSurface()->unlockBmps();
#ifdef __i386__
    // XXX Yuck
    if (!(getPlayer()->getDisplayEngine()->hasRGBOrdering())) {
        FilterFlipRGB().applyInPlace(m_pBmp);
    }
#endif
*/
    RasterNode::disconnect();
}

const std::string& Image::getHRef() const
{
    return m_href;
}

void Image::setHRef(const string& href)
{
    m_href = href;
    load();
    if (isDisplayAvailable()) {
        setupSurface(&*m_pBmp);
    }
    DPoint Size = getPreferredMediaSize();
    setViewport(-32767, -32767, Size.x, Size.y);
}

void Image::setBitmap(const Bitmap * pBmp)
{
    // TODO: Add a unique bitmap identifier to the URI.
    m_href = "mem://";
    PixelFormat pf;
    pf = R8G8B8X8;
    if (pBmp->hasAlpha()) {
        pf = R8G8B8A8;
    }
    if (pBmp->getPixelFormat() == I8) {
        pf = I8;
    }
#ifdef __i386__
    if (!(getPlayer()->getDisplayEngine()->hasRGBOrdering())) {
        switch (pf) {
            case R8G8B8X8:
                pf = B8G8R8X8;
                break;
            case R8G8B8A8:
                pf = B8G8R8A8;
                break;
            default:
                break;
        }
    }
#endif
//    cerr << "pf: " << Bitmap::getPixelFormatString(pf) << endl;
    getSurface()->create(pBmp->getSize(), pf, true);
    BitmapPtr pSurfaceBmp = getSurface()->lockBmp();
    pSurfaceBmp->copyPixels(*pBmp);
    getSurface()->unlockBmps();
    getEngine()->surfaceChanged(getSurface());
    DPoint Size = getPreferredMediaSize();
    setViewport(-32767, -32767, Size.x, Size.y);
}

static ProfilingZone RenderProfilingZone("    Image::render");

void Image::render (const DRect& Rect)
{
    ScopeTimer Timer(RenderProfilingZone);
    if (m_href != "") {
        getEngine()->blt32(getSurface(), &getAbsViewport(), getEffectiveOpacity(),
                getAngle(), getPivot(), getBlendMode());
    }
}

bool Image::obscures (const DRect& Rect, int Child)
{
    PixelFormat pf = getSurface()->getPixelFormat();
    bool bHasAlpha = (pf == R8G8B8A8 || pf == B8G8R8A8);
    return (isActive() && getEffectiveOpacity() > 0.999
            && bHasAlpha && getVisibleRect().Contains(Rect));
}

string Image::getTypeStr ()
{
    return "Image";
}

DPoint Image::getPreferredMediaSize()
{
    if (isDisplayAvailable()) {
        return DPoint(getSurface()->getSize());
    } else {
        return DPoint(m_pBmp->getSize());
    }
}

void Image::load()
{
    m_Filename = m_href;
    if (m_Filename != "") {
        initFilename(getPlayer(), m_Filename);
        AVG_TRACE(Logger::PROFILE, "Loading " << m_Filename);
        try {
            m_pBmp = BitmapPtr(new Bitmap(m_Filename));
        } catch (Magick::Exception & ex) {
            AVG_TRACE(Logger::ERROR, ex.what());
        }
    } else {
        m_pBmp = BitmapPtr(new Bitmap(IntPoint(1,1), R8G8B8X8));
    }
    if (m_Saturation != -1) {
        FilterColorize(m_Hue, m_Saturation).applyInPlace(
                m_pBmp);
    }
}

void Image::setupSurface(const Bitmap * pBmp)
{
    PixelFormat pf;
    pf = R8G8B8X8;
    if (pBmp->hasAlpha()) {
        pf = R8G8B8A8;
    }
    bool bUsePBO = true;
#ifdef __APPLE__
    if (getSurface()->wouldTile(pBmp->getSize())) {
        bUsePBO = false;
    }
#endif
    getSurface()->create(pBmp->getSize(), pf, bUsePBO);
    BitmapPtr pSurfaceBmp = getSurface()->lockBmp();
    pSurfaceBmp->copyPixels(*pBmp);
#ifdef __i386__
    if (!(getPlayer()->getDisplayEngine()->hasRGBOrdering())) {
        FilterFlipRGB().applyInPlace(pSurfaceBmp);
    }
#endif
    getSurface()->unlockBmps();
    getEngine()->surfaceChanged(getSurface());
//    m_pBmp=BitmapPtr();
}

}
<commit_msg>Fixed coverage test bug.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2006 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "Image.h"

#include "DisplayEngine.h"
#include "Player.h"
#include "ISurface.h"

#include "../graphics/Filtercolorize.h"
#include "../graphics/Filterfliprgb.h"

#include "../base/Logger.h"
#include "../base/ScopeTimer.h"
#include "../base/XMLHelper.h"

#include <Magick++.h>

#include <iostream>
#include <sstream>

using namespace std;

namespace avg {

Image::Image ()
    : m_Hue(-1),
      m_Saturation(-1)
{
    m_pBmp = BitmapPtr(new Bitmap(IntPoint(1,1), R8G8B8X8));
}

Image::Image (const xmlNodePtr xmlNode, Player * pPlayer)
    : RasterNode(xmlNode, pPlayer)
{
    m_href = getDefaultedStringAttr (xmlNode, "href", "");
    m_Hue = getDefaultedIntAttr (xmlNode, "hue", -1);
    m_Saturation = getDefaultedIntAttr (xmlNode, "saturation", -1);
    m_pBmp = BitmapPtr(new Bitmap(IntPoint(1,1), R8G8B8X8));
    load();
}

Image::~Image ()
{
}

void Image::setDisplayEngine(DisplayEngine * pEngine)
{
    RasterNode::setDisplayEngine(pEngine);

    setupSurface(&*m_pBmp);
}

void Image::disconnect()
{
/*
    // Commenting this (and the corresponding line in setupSurface) out causes
    // a copy of the image to always be kept in main memory, so no readback has to
    // take place.

    // Unload textures but keep bitmap in memory.
    ISurface * pSurface = getSurface();
    BitmapPtr pSurfaceBmp = pSurface->lockBmp();
    m_pBmp = BitmapPtr(new Bitmap(pSurfaceBmp->getSize(), pSurfaceBmp->getPixelFormat()));
    m_pBmp->copyPixels(*pSurfaceBmp);
    getSurface()->unlockBmps();
#ifdef __i386__
    // XXX Yuck
    if (!(getPlayer()->getDisplayEngine()->hasRGBOrdering())) {
        FilterFlipRGB().applyInPlace(m_pBmp);
    }
#endif
*/
    RasterNode::disconnect();
}

const std::string& Image::getHRef() const
{
    return m_href;
}

void Image::setHRef(const string& href)
{
    m_href = href;
    load();
    if (isDisplayAvailable()) {
        setupSurface(&*m_pBmp);
    }
    DPoint Size = getPreferredMediaSize();
    setViewport(-32767, -32767, Size.x, Size.y);
}

void Image::setBitmap(const Bitmap * pBmp)
{
    // TODO: Add a unique bitmap identifier to the URI.
    m_href = "mem://";
    PixelFormat pf;
    pf = R8G8B8X8;
    if (pBmp->hasAlpha()) {
        pf = R8G8B8A8;
    }
    if (pBmp->getPixelFormat() == I8) {
        pf = I8;
    }
#ifdef __i386__
    if (!(getPlayer()->getDisplayEngine()->hasRGBOrdering())) {
        switch (pf) {
            case R8G8B8X8:
                pf = B8G8R8X8;
                break;
            case R8G8B8A8:
                pf = B8G8R8A8;
                break;
            default:
                break;
        }
    }
#endif
//    cerr << "pf: " << Bitmap::getPixelFormatString(pf) << endl;
    getSurface()->create(pBmp->getSize(), pf, true);
    BitmapPtr pSurfaceBmp = getSurface()->lockBmp();
    pSurfaceBmp->copyPixels(*pBmp);
    getSurface()->unlockBmps();
    getEngine()->surfaceChanged(getSurface());
    DPoint Size = getPreferredMediaSize();
    setViewport(-32767, -32767, Size.x, Size.y);
}

static ProfilingZone RenderProfilingZone("    Image::render");

void Image::render (const DRect& Rect)
{
    ScopeTimer Timer(RenderProfilingZone);
    if (m_href != "") {
        getEngine()->blt32(getSurface(), &getAbsViewport(), getEffectiveOpacity(),
                getAngle(), getPivot(), getBlendMode());
    }
}

bool Image::obscures (const DRect& Rect, int Child)
{
    PixelFormat pf = getSurface()->getPixelFormat();
    bool bHasAlpha = (pf == R8G8B8A8 || pf == B8G8R8A8);
    return (isActive() && getEffectiveOpacity() > 0.999
            && !bHasAlpha && getVisibleRect().Contains(Rect));
}

string Image::getTypeStr ()
{
    return "Image";
}

DPoint Image::getPreferredMediaSize()
{
    if (isDisplayAvailable()) {
        return DPoint(getSurface()->getSize());
    } else {
        return DPoint(m_pBmp->getSize());
    }
}

void Image::load()
{
    m_Filename = m_href;
    if (m_Filename != "") {
        initFilename(getPlayer(), m_Filename);
        AVG_TRACE(Logger::PROFILE, "Loading " << m_Filename);
        try {
            m_pBmp = BitmapPtr(new Bitmap(m_Filename));
        } catch (Magick::Exception & ex) {
            AVG_TRACE(Logger::ERROR, ex.what());
        }
    } else {
        m_pBmp = BitmapPtr(new Bitmap(IntPoint(1,1), R8G8B8X8));
    }
    if (m_Saturation != -1) {
        FilterColorize(m_Hue, m_Saturation).applyInPlace(
                m_pBmp);
    }
}

void Image::setupSurface(const Bitmap * pBmp)
{
    PixelFormat pf;
    pf = R8G8B8X8;
    if (pBmp->hasAlpha()) {
        pf = R8G8B8A8;
    }
    bool bUsePBO = true;
#ifdef __APPLE__
    if (getSurface()->wouldTile(pBmp->getSize())) {
        bUsePBO = false;
    }
#endif
    getSurface()->create(pBmp->getSize(), pf, bUsePBO);
    BitmapPtr pSurfaceBmp = getSurface()->lockBmp();
    pSurfaceBmp->copyPixels(*pBmp);
#ifdef __i386__
    if (!(getPlayer()->getDisplayEngine()->hasRGBOrdering())) {
        FilterFlipRGB().applyInPlace(pSurfaceBmp);
    }
#endif
    getSurface()->unlockBmps();
    getEngine()->surfaceChanged(getSurface());
//    m_pBmp=BitmapPtr();
}

}
<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2006 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "Video.h"
#include "DisplayEngine.h"
#include "Player.h"
#include "ISurface.h"

#include "../base/Exception.h"
#include "../base/Logger.h"
#include "../base/ScopeTimer.h"
#include "../base/XMLHelper.h"

#include "../graphics/Filterflipuv.h"

#include "../video/AsyncVideoDecoder.h"
#include "../video/FFMpegDecoder.h"

#include <boost/python.hpp>

#include <iostream>
#include <sstream>
#include <unistd.h>

using namespace boost::python;
using namespace std;

namespace avg {

bool Video::m_bInitialized = false;

Video::Video ()
    : m_href(""),
      m_Filename(""),
      m_bLoop(false),
      m_pEOFCallback(0),
      m_pDecoder(0)
{
}

Video::Video (const xmlNodePtr xmlNode, Player * pPlayer)
    : VideoBase(xmlNode, pPlayer),
      m_Filename(""),
      m_pEOFCallback(0),
      m_pDecoder(0)
{
    m_href = getDefaultedStringAttr (xmlNode, "href", "");
    m_bLoop = getDefaultedBoolAttr (xmlNode, "loop", false);
    m_bThreaded = getDefaultedBoolAttr (xmlNode, "threaded", false);
    m_Filename = m_href;
    if (m_Filename != "") {
        initFilename(getPlayer(), m_Filename);
    }
    if (m_bThreaded) {
        VideoDecoderPtr pSyncDecoder = VideoDecoderPtr(new FFMpegDecoder());
        m_pDecoder = new AsyncVideoDecoder(pSyncDecoder);
    } else {
        m_pDecoder = new FFMpegDecoder();
    }
}

Video::~Video ()
{
    if (m_pDecoder) {
        delete m_pDecoder;
        m_pDecoder = 0;
    }
    if (m_pEOFCallback) {
        Py_DECREF(m_pEOFCallback);
    }
}

int Video::getNumFrames() const
{
    if (getVideoState() != Unloaded) {
        return m_pDecoder->getNumFrames();
    } else {
        AVG_TRACE(Logger::WARNING,
               "Error in Video::getNumFrames: Video not loaded.");
        return -1;
    }
}

int Video::getCurFrame() const
{
    if (getVideoState() != Unloaded) {
        return m_CurFrame;
    } else {
        AVG_TRACE(Logger::WARNING,
                "Error in Video::GetCurFrame: Video not loaded.");
        return -1;
    }
}

void Video::seekToFrame(int num)
{
    if (getVideoState() != Unloaded) {
        seek(num);
    } else {
        AVG_TRACE(Logger::WARNING,
                "Error in Video::SeekToFrame: Video "+getID()+" not loaded.");
    }
}

bool Video::getLoop() const
{
    return m_bLoop;
}

bool Video::isThreaded() const
{
    return m_bThreaded;
}

void Video::setEOFCallback(PyObject * pEOFCallback)
{
    if (m_pEOFCallback) {
        Py_DECREF(m_pEOFCallback);
    }
    Py_INCREF(pEOFCallback);
    m_pEOFCallback = pEOFCallback;
}

void Video::setDisplayEngine(DisplayEngine * pEngine)
{
    VideoBase::setDisplayEngine(pEngine);
}

void Video::disconnect()
{
    stop();
    VideoBase::disconnect();
}

const string& Video::getHRef() const
{
    return m_Filename;
}

void Video::setHRef(const string& href)
{
    string fileName (href);
    m_href = href;
    if (m_href != "") {
        initFilename(getPlayer(), fileName);
        if (fileName != m_Filename) {
            changeVideoState(Unloaded);
            m_Filename = fileName;
            changeVideoState(Paused);
        }
    } else {
        changeVideoState(Unloaded);
        m_Filename = "";
    }
}

string Video::getTypeStr ()
{
    return "Video";
}

void Video::changeVideoState(VideoState NewVideoState)
{
    long long CurTime = getPlayer()->getFrameTime();
    if (NewVideoState != getVideoState()) {
        if (getVideoState() == Unloaded) {
            m_StartTime = CurTime;
            m_PauseTime = 0;
        }
        if (NewVideoState == Paused) {
            m_PauseStartTime = CurTime;
        } else if (NewVideoState == Playing && getVideoState() == Paused) {
            m_PauseTime += (CurTime-m_PauseStartTime);
        }
    }
    VideoBase::changeVideoState(NewVideoState);
}

void Video::seek(int DestFrame)
{

    m_pDecoder->seek(DestFrame);
    m_StartTime = getPlayer()->getFrameTime()
            -(long long)((DestFrame*1000.0)/m_pDecoder->getFPS());
    m_PauseTime = 0;
    m_PauseStartTime = getPlayer()->getFrameTime();
    m_CurFrame = DestFrame;
    setFrameAvailable(false);
}

void Video::open(YCbCrMode ycbcrMode)
{
    m_CurFrame = 0;
    m_pDecoder->open(m_Filename, ycbcrMode, m_bThreaded);
}

void Video::close()
{
    m_pDecoder->close();
}

PixelFormat Video::getPixelFormat()
{
    return m_pDecoder->getPixelFormat();
}

IntPoint Video::getSize()
{
    if (m_pDecoder)  {
        return m_pDecoder->getSize();
    } else {
        return IntPoint(0,0);
    }
}

double Video::getFPS()
{
    return m_pDecoder->getFPS();
}

long long Video::getCurTime()
{
    switch (getVideoState()) {
        case Unloaded:
            return 0;
        case Paused:
            return m_PauseStartTime-m_StartTime;
        case Playing:
            return getPlayer()->getFrameTime()-m_StartTime-m_PauseTime;
        default:
            assert(false);
            return 0;
    }
}

static ProfilingZone RenderProfilingZone("    Video::render");

bool Video::renderToSurface(ISurface * pSurface)
{
    ScopeTimer Timer(RenderProfilingZone);
    PixelFormat PF = m_pDecoder->getPixelFormat();
    FrameAvailableCode FrameAvailable;
    if (PF == YCbCr420p || PF == YCbCrJ420p) {
        BitmapPtr pBmp = pSurface->lockBmp(0);
        FrameAvailable = m_pDecoder->renderToYCbCr420p(pBmp,
                pSurface->lockBmp(1), pSurface->lockBmp(2), getCurTime());
    } else {
        BitmapPtr pBmp = pSurface->lockBmp();
        FrameAvailable = m_pDecoder->renderToBmp(pBmp, getCurTime());
//        DisplayEngine::YCbCrMode ycbcrMode = getEngine()->getYCbCrMode();
//        if (ycbcrMode == DisplayEngine::OGL_MESA && pBmp->getPixelFormat() == YCbCr422) {
//            FilterFlipUV().applyInPlace(pBmp);
//        }
    }
    pSurface->unlockBmps();
    if (FrameAvailable == FA_NEW_FRAME) {
        getEngine()->surfaceChanged(pSurface);
    }
    if (getVideoState() == Playing) {
        advancePlayback();
    }
    return (FrameAvailable == FA_NEW_FRAME);
}

void Video::onEOF()
{
    if (m_pEOFCallback) {
        PyObject * arglist = Py_BuildValue("()");
        PyObject * result = PyEval_CallObject(m_pEOFCallback, arglist);
        Py_DECREF(arglist);
        if (!result) {
            throw error_already_set();
        }
        Py_DECREF(result);
    }
}

void Video::advancePlayback()
{
    m_CurFrame++;
    if (m_pDecoder->isEOF()) {
        onEOF();
        if (m_bLoop) {
            seek(0);
        } else {
            changeVideoState(Paused);
        }
    }
}

}
<commit_msg>Seek optimization.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2006 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "Video.h"
#include "DisplayEngine.h"
#include "Player.h"
#include "ISurface.h"

#include "../base/Exception.h"
#include "../base/Logger.h"
#include "../base/ScopeTimer.h"
#include "../base/XMLHelper.h"

#include "../graphics/Filterflipuv.h"

#include "../video/AsyncVideoDecoder.h"
#include "../video/FFMpegDecoder.h"

#include <boost/python.hpp>

#include <iostream>
#include <sstream>
#include <unistd.h>

using namespace boost::python;
using namespace std;

namespace avg {

bool Video::m_bInitialized = false;

Video::Video ()
    : m_href(""),
      m_Filename(""),
      m_bLoop(false),
      m_pEOFCallback(0),
      m_pDecoder(0)
{
}

Video::Video (const xmlNodePtr xmlNode, Player * pPlayer)
    : VideoBase(xmlNode, pPlayer),
      m_Filename(""),
      m_pEOFCallback(0),
      m_pDecoder(0)
{
    m_href = getDefaultedStringAttr (xmlNode, "href", "");
    m_bLoop = getDefaultedBoolAttr (xmlNode, "loop", false);
    m_bThreaded = getDefaultedBoolAttr (xmlNode, "threaded", false);
    m_Filename = m_href;
    if (m_Filename != "") {
        initFilename(getPlayer(), m_Filename);
    }
    if (m_bThreaded) {
        VideoDecoderPtr pSyncDecoder = VideoDecoderPtr(new FFMpegDecoder());
        m_pDecoder = new AsyncVideoDecoder(pSyncDecoder);
    } else {
        m_pDecoder = new FFMpegDecoder();
    }
}

Video::~Video ()
{
    if (m_pDecoder) {
        delete m_pDecoder;
        m_pDecoder = 0;
    }
    if (m_pEOFCallback) {
        Py_DECREF(m_pEOFCallback);
    }
}

int Video::getNumFrames() const
{
    if (getVideoState() != Unloaded) {
        return m_pDecoder->getNumFrames();
    } else {
        AVG_TRACE(Logger::WARNING,
               "Error in Video::getNumFrames: Video not loaded.");
        return -1;
    }
}

int Video::getCurFrame() const
{
    if (getVideoState() != Unloaded) {
        return m_CurFrame;
    } else {
        AVG_TRACE(Logger::WARNING,
                "Error in Video::GetCurFrame: Video not loaded.");
        return -1;
    }
}

void Video::seekToFrame(int num)
{
    if (getVideoState() != Unloaded) {
        if (num != m_CurFrame) {
            seek(num);
        }
    } else {
        AVG_TRACE(Logger::WARNING,
                "Error in Video::SeekToFrame: Video "+getID()+" not loaded.");
    }
}

bool Video::getLoop() const
{
    return m_bLoop;
}

bool Video::isThreaded() const
{
    return m_bThreaded;
}

void Video::setEOFCallback(PyObject * pEOFCallback)
{
    if (m_pEOFCallback) {
        Py_DECREF(m_pEOFCallback);
    }
    Py_INCREF(pEOFCallback);
    m_pEOFCallback = pEOFCallback;
}

void Video::setDisplayEngine(DisplayEngine * pEngine)
{
    VideoBase::setDisplayEngine(pEngine);
}

void Video::disconnect()
{
    stop();
    VideoBase::disconnect();
}

const string& Video::getHRef() const
{
    return m_Filename;
}

void Video::setHRef(const string& href)
{
    string fileName (href);
    m_href = href;
    if (m_href != "") {
        initFilename(getPlayer(), fileName);
        if (fileName != m_Filename) {
            changeVideoState(Unloaded);
            m_Filename = fileName;
            changeVideoState(Paused);
        }
    } else {
        changeVideoState(Unloaded);
        m_Filename = "";
    }
}

string Video::getTypeStr ()
{
    return "Video";
}

void Video::changeVideoState(VideoState NewVideoState)
{
    long long CurTime = getPlayer()->getFrameTime();
    if (NewVideoState != getVideoState()) {
        if (getVideoState() == Unloaded) {
            m_StartTime = CurTime;
            m_PauseTime = 0;
        }
        if (NewVideoState == Paused) {
            m_PauseStartTime = CurTime;
        } else if (NewVideoState == Playing && getVideoState() == Paused) {
            m_PauseTime += (CurTime-m_PauseStartTime);
        }
    }
    VideoBase::changeVideoState(NewVideoState);
}

void Video::seek(int DestFrame)
{

    m_pDecoder->seek(DestFrame);
    m_StartTime = getPlayer()->getFrameTime()
            -(long long)((DestFrame*1000.0)/m_pDecoder->getFPS());
    m_PauseTime = 0;
    m_PauseStartTime = getPlayer()->getFrameTime();
    m_CurFrame = DestFrame;
    setFrameAvailable(false);
}

void Video::open(YCbCrMode ycbcrMode)
{
    m_CurFrame = 0;
    m_pDecoder->open(m_Filename, ycbcrMode, m_bThreaded);
}

void Video::close()
{
    m_pDecoder->close();
}

PixelFormat Video::getPixelFormat()
{
    return m_pDecoder->getPixelFormat();
}

IntPoint Video::getSize()
{
    if (m_pDecoder)  {
        return m_pDecoder->getSize();
    } else {
        return IntPoint(0,0);
    }
}

double Video::getFPS()
{
    return m_pDecoder->getFPS();
}

long long Video::getCurTime()
{
    switch (getVideoState()) {
        case Unloaded:
            return 0;
        case Paused:
            return m_PauseStartTime-m_StartTime;
        case Playing:
            return getPlayer()->getFrameTime()-m_StartTime-m_PauseTime;
        default:
            assert(false);
            return 0;
    }
}

static ProfilingZone RenderProfilingZone("    Video::render");

bool Video::renderToSurface(ISurface * pSurface)
{
    ScopeTimer Timer(RenderProfilingZone);
    PixelFormat PF = m_pDecoder->getPixelFormat();
    FrameAvailableCode FrameAvailable;
    if (PF == YCbCr420p || PF == YCbCrJ420p) {
        BitmapPtr pBmp = pSurface->lockBmp(0);
        FrameAvailable = m_pDecoder->renderToYCbCr420p(pBmp,
                pSurface->lockBmp(1), pSurface->lockBmp(2), getCurTime());
    } else {
        BitmapPtr pBmp = pSurface->lockBmp();
        FrameAvailable = m_pDecoder->renderToBmp(pBmp, getCurTime());
//        DisplayEngine::YCbCrMode ycbcrMode = getEngine()->getYCbCrMode();
//        if (ycbcrMode == DisplayEngine::OGL_MESA && pBmp->getPixelFormat() == YCbCr422) {
//            FilterFlipUV().applyInPlace(pBmp);
//        }
    }
    pSurface->unlockBmps();
    if (FrameAvailable == FA_NEW_FRAME) {
        getEngine()->surfaceChanged(pSurface);
    }
    if (getVideoState() == Playing) {
        advancePlayback();
    }
    return (FrameAvailable == FA_NEW_FRAME);
}

void Video::onEOF()
{
    if (m_pEOFCallback) {
        PyObject * arglist = Py_BuildValue("()");
        PyObject * result = PyEval_CallObject(m_pEOFCallback, arglist);
        Py_DECREF(arglist);
        if (!result) {
            throw error_already_set();
        }
        Py_DECREF(result);
    }
}

void Video::advancePlayback()
{
    m_CurFrame++;
    if (m_pDecoder->isEOF()) {
        onEOF();
        if (m_bLoop) {
            seek(0);
        } else {
            changeVideoState(Paused);
        }
    }
}

}
<|endoftext|>


<commit_before>/*******************************************************************************
Copyright (c) 2014, Jan Koester jan.koester@gmx.net
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/

#include <fcntl.h>
#include <sys/epoll.h>
#include <cstdlib>
#include <config.h>
#include <errno.h>

#define READEVENT 0
#define SENDEVENT 1

#include "../queue.h"

using namespace libhttppp;

Queue::Queue(ServerSocket *socket) : ConnectionPool(socket) {
  struct epoll_event *events;
  struct epoll_event  event = {0};
  events = new epoll_event[(socket->getMaxconnections()*sizeof(struct epoll_event))];
  for(int i=0; i<socket->getMaxconnections(); i++)
    events[i].data.fd = -1;
  int epollfd = epoll_create(socket->getMaxconnections());

  if (epollfd == -1){
    _httpexception.Cirtical("can't create epoll");
    throw _httpexception;
  }

  event.events = EPOLLIN | EPOLLRDHUP;
  event.data.fd = socket->getSocket();
  if (epoll_ctl(epollfd, EPOLL_CTL_ADD, socket->getSocket(), &event) < 0){
    _httpexception.Cirtical("can't create epoll");
    throw _httpexception;
  }

  for(;;){
    int n = epoll_wait(epollfd, events, socket->getMaxconnections(), EPOLLWAIT);
    for(int i=0; i<n; i++) {
      Connection *curcon=NULL;
      if(events[i].data.fd == socket->getSocket()) {
        try{
          /*will create warning debug mode that normally because the check already connection
           * with this socket if getconnection throw they will be create a new one
           */
	  curcon=addConnection();
	  ClientSocket *clientsocket=curcon->getClientSocket();
	  clientsocket->setnonblocking();
          event.data.fd =_ServerSocket->acceptEvent(clientsocket);
          event.events = EPOLLIN | EPOLLRDHUP;

          if(epoll_ctl(epollfd, EPOLL_CTL_ADD, event.data.fd, &event)==-1 && errno==EEXIST)
            epoll_ctl(epollfd, EPOLL_CTL_MOD, events[i].data.fd, &event);
        }catch(HTTPException &e){
          if(e.isCritical())
            throw e;
        }
        continue;
      }else{
	curcon=getConnection(events[i].data.fd);
      }

      if(events[i].events & EPOLLIN){
          try{
            char buf[BLOCKSIZE];
            int rcvsize=_ServerSocket->recvData(curcon->getClientSocket(),buf,BLOCKSIZE);
            if(rcvsize==-1){
               if (errno == EAGAIN)
                 continue;
               else
                 goto CloseConnection;
            }
            curcon->addRecvQueue(buf,rcvsize);
            RequestEvent(curcon);
            if(curcon->getSendData()){
              event.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP;
              epoll_ctl(epollfd, EPOLL_CTL_MOD, events[i].data.fd, &event);
	      _httpexception.Note("switch to send mode!");
            }
          }catch(HTTPException &e){
            if(e.isCritical()){
              throw e;
            }
            if(e.isError())
             goto CloseConnection;
          }
      }

      if(events[i].events & EPOLLOUT) {
        try{
          if(curcon->getSendData()){
            ssize_t sended=_ServerSocket->sendData(curcon->getClientSocket(),
                                                   (void*)curcon->getSendData()->getData(),
                                                    curcon->getSendData()->getDataSize());
            if(sended==-1){
              _httpexception.Note("Sending Failed");
              if (errno == EAGAIN){
                continue;
              }else{
		curcon->cleanSendData();
                goto CloseConnection;
	      }
            }else{
              curcon->resizeSendQueue(sended);
            }
            continue;
          }else{
              event.events = EPOLLIN | EPOLLRDHUP;
              epoll_ctl(epollfd, EPOLL_CTL_MOD, events[i].data.fd, &event);
	      _httpexception.Note("switch to recv mode!");
          }
        }catch(HTTPException &e){
           goto CloseConnection;
        }
      }

      if(events[i].events & EPOLLRDHUP || events[i].events & EPOLLERR) {
          CloseConnection:
            try{
              delConnection(curcon);
              epoll_ctl(epollfd, EPOLL_CTL_DEL, events[i].data.fd, &event);
            }catch(HTTPException &e){
              delConnection(curcon);
            }
          ;
      }
    }
  }
  delete events;

}

Queue::~Queue(){

}<commit_msg>fixed chrome bug<commit_after>/*******************************************************************************
Copyright (c) 2014, Jan Koester jan.koester@gmx.net
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************/

#include <fcntl.h>
#include <sys/epoll.h>
#include <cstdlib>
#include <config.h>
#include <errno.h>

#define READEVENT 0
#define SENDEVENT 1

#include "../queue.h"

using namespace libhttppp;

Queue::Queue(ServerSocket *socket) : ConnectionPool(socket) {
  struct epoll_event *events;
  struct epoll_event  event = {0};
  events = new epoll_event[(socket->getMaxconnections()*sizeof(struct epoll_event))];
  for(int i=0; i<socket->getMaxconnections(); i++)
    events[i].data.fd = -1;
  int epollfd = epoll_create(socket->getMaxconnections());

  if (epollfd == -1){
    _httpexception.Cirtical("can't create epoll");
    throw _httpexception;
  }

  event.events = EPOLLIN | EPOLLRDHUP;
  event.data.fd = socket->getSocket();
  if (epoll_ctl(epollfd, EPOLL_CTL_ADD, socket->getSocket(), &event) < 0){
    _httpexception.Cirtical("can't create epoll");
    throw _httpexception;
  }

  for(;;){
    int n = epoll_wait(epollfd, events, socket->getMaxconnections(), EPOLLWAIT);
    for(int i=0; i<n; i++) {
      Connection *curcon=NULL;
      if(events[i].data.fd == socket->getSocket()) {
        try{
          /*will create warning debug mode that normally because the check already connection
           * with this socket if getconnection throw they will be create a new one
           */
	  curcon=addConnection();
	  ClientSocket *clientsocket=curcon->getClientSocket();
	  clientsocket->setnonblocking();
          event.data.fd =_ServerSocket->acceptEvent(clientsocket);
          event.events = EPOLLIN | EPOLLRDHUP;

          if(epoll_ctl(epollfd, EPOLL_CTL_ADD, event.data.fd, &event)==-1 && errno==EEXIST)
            epoll_ctl(epollfd, EPOLL_CTL_MOD, events[i].data.fd, &event);
        }catch(HTTPException &e){
          if(e.isCritical())
            throw e;
        }
        continue;
      }else{
	curcon=getConnection(events[i].data.fd);
      }

      if(events[i].events & EPOLLIN){
          try{
            char buf[BLOCKSIZE];
            int rcvsize=_ServerSocket->recvData(curcon->getClientSocket(),buf,BLOCKSIZE);
            if(rcvsize==-1){
               if (errno == EAGAIN)
                 continue;
               else
                 goto CloseConnection;
            }
            curcon->addRecvQueue(buf,rcvsize);
            RequestEvent(curcon);
            if(curcon->getSendData()){
              event.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP;
              epoll_ctl(epollfd, EPOLL_CTL_MOD, events[i].data.fd, &event);
	      _httpexception.Note("switch to send mode!");
            }
          }catch(HTTPException &e){
            if(e.isCritical()){
              throw e;
            }
            if(e.isError())
             goto CloseConnection;
          }
      }

      if(events[i].events & EPOLLOUT) {
        try{
          if(curcon->getSendData()){
            ssize_t sended=_ServerSocket->sendData(curcon->getClientSocket(),
                                                   (void*)curcon->getSendData()->getData(),
                                                    curcon->getSendData()->getDataSize());
            if(sended==-1){
              _httpexception.Note("Sending Failed");
              if (errno == EAGAIN){
                continue;
              }else{
		curcon->cleanSendData();
                goto CloseConnection;
	      }
            }else{
              curcon->resizeSendQueue(sended);
            }
          }else{
              event.events = EPOLLIN | EPOLLRDHUP;
              epoll_ctl(epollfd, EPOLL_CTL_MOD, events[i].data.fd, &event);
	      _httpexception.Note("switch to recv mode!");
          }
        }catch(HTTPException &e){
           goto CloseConnection;
        }
      }

      if(events[i].events & EPOLLRDHUP || events[i].events & EPOLLERR) {
          CloseConnection:
            try{
              delConnection(curcon);
              epoll_ctl(epollfd, EPOLL_CTL_DEL, events[i].data.fd, &event);
	      _httpexception.Note("Connection shutdown!");
            }catch(HTTPException &e){
              delConnection(curcon);
            }
          ;
      }
    }
  }
  delete events;

}

Queue::~Queue(){

}<|endoftext|>


<commit_before>/*
 *   Copyright (c) 2012 Memphis-CS Genome Assembly Group
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *
 *   1. Redistributions of source code must retain the above Copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above Copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 *   3. Neither the name of the authors nor the names of its contributors
 *      may be used to endorse or promote products derived from this
 *      software without specific prior written permission.
*/

#include <cstring>
#include <algorithm>
#include <sstream>
#include <math.h>

#include "randal_search.hpp"

using namespace std;

class Parameter
{
    public:
        string infoRead;
        string nameRead;
        string CIGAR;
        string qualRead;
        int flag;
};

void usage();
void printParameters();
void parse_parameters (int argc, char **argv);

string reverseRead(string& rea);
template <class T> string to_string1(T t);
void process(string& r, Parameter& pa);
void alignReads(const string& r, const Parameter& p, uint64_t pos);

char *backwardIndexFile;
char *forwardIndexFile;
char *refFile;
char *readFile;
char *mapFile;

int length;
float error_prob = -1;
int att_para = -1;
int th_para = -1;

int mode = -1;
int th = -1;
int att = -1;
int rep = -1;
int minws = -1;
int maxcdt = -1;

uint32_t num = 0;
randal_search ra;

ifstream infile;
ofstream outfile;

int main(int argc, char **argv)
{
    if (argc < 4)
    {
        usage();
    }
    else
    {
        parse_parameters(argc, argv);
    }

    srand(time(NULL)); //initialize the random generator

    infile.open(readFile);     //Read the read file (*.fq)
    outfile.open(mapFile);     //Open the map file (*.sam)
    string r = "";
    Parameter para;
    getline(infile, r);     //The 1st read
    para.infoRead = r.erase(0, 1);
    para.nameRead = r.substr(0, r.find("_"));
    string read1st = "";
    getline(infile, read1st);

    //Set parameters
    length = read1st.length();
    if (error_prob == -1) error_prob = 0.02;
    if (att_para == -1) att_para = 1;
    if (th_para == -1) th_para = 4;

    if (mode == -1) mode = 3;
    if (rep == -1) rep = 10;
    if (maxcdt == -1) maxcdt = 2;

    if (th == -1) th = int(floor(error_prob * length + th_para * sqrt(length * error_prob * (1 - error_prob))));
    if (att == -1) att = att_para * (th + 1);
    if (minws == -1) minws = int(ceil(length/(th + 1))) + 3;

    printParameters();
    ra.Init(mode, rep, th, att, minws, backwardIndexFile, forwardIndexFile, refFile);

    para.CIGAR = to_string1(read1st.length()) + "M";
    getline(infile, r);
    getline(infile, para.qualRead);

    process(read1st, para);

    //For each line (read) find the match positions and store those positions to output file
    while (getline(infile, r))
    {
        if (r[0] == '@')
        {
            para.infoRead = r.erase(0, 1);
            getline(infile, r);
            process(r, para);
        }
    }
    infile.close();
    outfile.close();
    cout << "Finish aligning reads, number of mapped reads: " << num << endl;
}

//
void process(string& r, Parameter& pa)
{
    vector<size_t> positions;
    vector<uint16_t> distances;
    ra.AlignRead(r, positions, distances);
    string rr;
    size_t pos=0;
    int dis;

    if (positions.empty())
    {
        rr = reverseRead(r);
        ra.AlignRead(rr, positions, distances);
        if (positions.empty())
        {
            pa.flag = 4;
            alignReads(rr, pa, pos);
        }
        else
        {
            dis = distances[0];
            pos = positions[0];
			if (positions.size() > maxcdt)
				return;
            for (unsigned int i = 0 ; i < positions.size() ; i++)
            {
                if (distances[i] == 0)
                {
                    pos = positions[i];
                    break;
                }
                if (dis > distances[i])
                {
                    dis = distances[i];
                    pos = positions[i];
                }
            }
            pa.flag = 16;
            alignReads(rr, pa, pos);
            num++;
        }
    }
    else
    {
        dis = distances[0];
        pos = positions[0];
	    if (positions.size() > maxcdt)
			return;
        for (unsigned int i=0; i<positions.size(); i++)
        {
            if (distances[i] == 0)
            {
                pos = positions[i];
                break;
            }
            if (dis > distances[i])
            {
                dis = distances[i];
                pos = positions[i];
            }
        }
        pa.flag = 0;
        alignReads(r, pa, pos);
        num++;
     }
}

//
template <class T> string to_string1(T t)
{
    stringstream ss;
    ss << t;
    return ss.str();
}

//
inline string reverseRead(string& rea)
{
    string t = "";
    for (size_t i=0; i<rea.length(); i++)
    {
        if (rea[i] =='A') t = t+'T'; else
        if (rea[i] =='T') t = t+'A'; else
        if (rea[i] =='G') t = t+'C'; else
        if (rea[i] =='C') t = t+'G'; else
        t = t+rea[i];
    }
    reverse(t.begin(), t.end());
    return t;
}

//
inline void alignReads(const string& r, const Parameter& p, uint64_t pos)
{
    if (p.flag == 4)
    {
        outfile << p.infoRead << "\t" << p.flag << "\t*\t0\t0\t*\t*\t0\t0\t";
        outfile << r << "\t" << p.qualRead << endl;
    }
    else
    {
        outfile << p.infoRead << "\t" << p.flag << "\t" << p.nameRead << "\t" << pos << "\t" << "255\t" << p.CIGAR << " \t*\t0\t0\t";
        outfile << r << "\t" << p.qualRead << endl;
    }
}

//
void usage()
{
    cerr << endl
    << "Usage:  randal IndexFileName ReadFileName MapFileName [OPTIONS]" << endl
    << "        IndexFileName           : index file name (from preprocessing step with rand-build)" << endl
    << "        ReadFileName            : read file name (in FASTQ format)" << endl
    << "        MapFileName             : file to store alignment result (in SAM format)" << endl
    << "        [OPTION]            : a list of zero or more optional arguments" << endl
    << "                -mode number    : distance mode (2:hamming distance; 3:edit distance; default 3)" << endl
    << "                -th number      : threshould for distance (integer, >= 0)" << endl
    << "                -att number     : number of attempts for the randomization (integer, > 0)" << endl
    << "                -minws number   : minimal length of common substring between read and reference (integer, > 0, < read length)" << endl
    << "                -maxcdt number  : maximal number of candidates for alignment (integer, > 0)" << endl;
    exit(0);
}

//
void printParameters()
{
    cout << "\nParameters:\n"
         << "Distance mode: " << mode << ", Distance threshold: " << th
         << ", Number of atempts: " << att << ", Minimal LCS: " << minws << ", Maximal alignment: " << maxcdt
         << ", Backward Index File: " << backwardIndexFile << ", Forward Index File: " << forwardIndexFile
         << ", Reference File: " << refFile << ", Read File: " << readFile << ", Map File:" << mapFile << endl;
}

//
void parse_parameters (int argc, char **argv)
{
    char *indexFile;
    // the first three arguments shouldn't start with minus
    if(argv[1][0] == '-' ||argv[2][0] == '-'||argv[3][0] == '-')
    {
        usage();
        return;
    }
    indexFile   = argv[1];
    readFile    = argv[2];
    mapFile     = argv[3];

    char *ref_ext = ".ref";
    char *bw_ext = ".bw";
    char *fw_ext = ".fw";
    int len = strlen(indexFile);
    refFile = new char[len + 3];
    backwardIndexFile = new char[len + 2];
    forwardIndexFile = new char[len + 2];
    strcpy(refFile, indexFile);
    strcat(refFile, ref_ext);
    strcpy(backwardIndexFile, indexFile);
    strcat(backwardIndexFile, bw_ext);
    strcpy(forwardIndexFile, indexFile);
    strcat(forwardIndexFile, fw_ext);

    int argno;
    for (argno = 4; argno < argc - 1; argno++)
    {
        if (argv[argno][0] == '-')
        {
            if (!strcmp (argv[argno], "-mode"))
            {
                if (argno == argc - 1) std::cerr << "Must specify searching mode after -mode" << std::endl;
                mode = atoi(argv[++argno]);
                if ((mode != 1) && (mode != 2) && (mode != 3))
                {
                    usage();
                    return;
                }
            }
            else if (!strcmp (argv[argno], "-th"))
            {
                if (argno == argc - 1) std::cerr << "Must specify threshold after -th" << std::endl;
                th = atoi(argv[++argno]);
                if (th < 0)
                {
                    usage();
                    return;
                }
            }
            else if (!strcmp (argv[argno], "-att"))
            {
                if (argno == argc - 1) std::cerr << "Must specify number of attempts after -att" << std::endl;
                att = atoi(argv[++argno]);
                if (att <= 0)
                {
                    usage();
                    return;
                }
            }
            else if (!strcmp (argv[argno], "-minws"))
            {
                if (argno == argc - 1) std::cerr << "Must specify minimal length of common substring between read and reference after -minws" << std::endl;
                minws = atoi(argv[++argno]);
                if (minws <= 0)
                {
                    usage();
                    return;
                }
            }
            else if (!strcmp (argv[argno], "-maxcdt"))
            {
                if (argno == argc - 1) std::cerr << "Must specify maximal number of candidates for alignment after -maxcdt" << std::endl;
                maxcdt = atoi(argv[++argno]);
                if (maxcdt <= 0)
                {
                    usage();
                    return;
                }
            }
        }
    }
}
<commit_msg>Fix a bug on assigning names for index files.<commit_after>/*
 *   Copyright (c) 2012 Memphis-CS Genome Assembly Group
 *
 *   Redistribution and use in source and binary forms, with or without
 *   modification, are permitted provided that the following conditions
 *   are met:
 *
 *   1. Redistributions of source code must retain the above Copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above Copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 *   3. Neither the name of the authors nor the names of its contributors
 *      may be used to endorse or promote products derived from this
 *      software without specific prior written permission.
*/

#include <cstring>
#include <algorithm>
#include <sstream>
#include <math.h>

#include "randal_search.hpp"

using namespace std;

class Parameter
{
    public:
        string infoRead;
        string nameRead;
        string CIGAR;
        string qualRead;
        int flag;
};

void usage();
void printParameters();
void parse_parameters (int argc, char **argv);

string reverseRead(string& rea);
template <class T> string to_string1(T t);
void process(string& r, Parameter& pa);
void alignReads(const string& r, const Parameter& p, uint64_t pos);

char *backwardIndexFile;
char *forwardIndexFile;
char *refFile;
char *readFile;
char *mapFile;

int length;
float error_prob = -1;
int att_para = -1;
int th_para = -1;

int mode = -1;
int th = -1;
int att = -1;
int rep = -1;
int minws = -1;
int maxcdt = -1;

uint32_t num = 0;
randal_search ra;

ifstream infile;
ofstream outfile;

int main(int argc, char **argv)
{
    if (argc < 4)
    {
        usage();
    }
    else
    {
        parse_parameters(argc, argv);
    }

    srand(time(NULL)); //initialize the random generator

    infile.open(readFile);     //Read the read file (*.fq)
    outfile.open(mapFile);     //Open the map file (*.sam)
    string r = "";
    Parameter para;
    getline(infile, r);     //The 1st read
    para.infoRead = r.erase(0, 1);
    para.nameRead = r.substr(0, r.find("_"));
    string read1st = "";
    getline(infile, read1st);

    //Set parameters
    length = read1st.length();
    if (error_prob == -1) error_prob = 0.02;
    if (att_para == -1) att_para = 1;
    if (th_para == -1) th_para = 4;

    if (mode == -1) mode = 3;
    if (rep == -1) rep = 10;
    if (maxcdt == -1) maxcdt = 2;

    if (th == -1) th = int(floor(error_prob * length + th_para * sqrt(length * error_prob * (1 - error_prob))));
    if (att == -1) att = att_para * (th + 1);
    if (minws == -1) minws = int(ceil(length/(th + 1))) + 3;

    printParameters();
    ra.Init(mode, rep, th, att, minws, backwardIndexFile, forwardIndexFile, refFile);

    para.CIGAR = to_string1(read1st.length()) + "M";
    getline(infile, r);
    getline(infile, para.qualRead);

    process(read1st, para);

    //For each line (read) find the match positions and store those positions to output file
    while (getline(infile, r))
    {
        if (r[0] == '@')
        {
            para.infoRead = r.erase(0, 1);
            getline(infile, r);
            process(r, para);
        }
    }
    infile.close();
    outfile.close();
    cout << "Finish aligning reads, number of mapped reads: " << num << endl;
}

//
void process(string& r, Parameter& pa)
{
    vector<size_t> positions;
    vector<uint16_t> distances;
    ra.AlignRead(r, positions, distances);
    string rr;
    size_t pos=0;
    int dis;

    if (positions.empty())
    {
        rr = reverseRead(r);
        ra.AlignRead(rr, positions, distances);
        if (positions.empty())
        {
            pa.flag = 4;
            alignReads(rr, pa, pos);
        }
        else
        {
            dis = distances[0];
            pos = positions[0];
			if (positions.size() > maxcdt)
				return;
            for (unsigned int i = 0 ; i < positions.size() ; i++)
            {
                if (distances[i] == 0)
                {
                    pos = positions[i];
                    break;
                }
                if (dis > distances[i])
                {
                    dis = distances[i];
                    pos = positions[i];
                }
            }
            pa.flag = 16;
            alignReads(rr, pa, pos);
            num++;
        }
    }
    else
    {
        dis = distances[0];
        pos = positions[0];
	    if (positions.size() > maxcdt)
			return;
        for (unsigned int i=0; i<positions.size(); i++)
        {
            if (distances[i] == 0)
            {
                pos = positions[i];
                break;
            }
            if (dis > distances[i])
            {
                dis = distances[i];
                pos = positions[i];
            }
        }
        pa.flag = 0;
        alignReads(r, pa, pos);
        num++;
     }
}

//
template <class T> string to_string1(T t)
{
    stringstream ss;
    ss << t;
    return ss.str();
}

//
inline string reverseRead(string& rea)
{
    string t = "";
    for (size_t i=0; i<rea.length(); i++)
    {
        if (rea[i] =='A') t = t+'T'; else
        if (rea[i] =='T') t = t+'A'; else
        if (rea[i] =='G') t = t+'C'; else
        if (rea[i] =='C') t = t+'G'; else
        t = t+rea[i];
    }
    reverse(t.begin(), t.end());
    return t;
}

//
inline void alignReads(const string& r, const Parameter& p, uint64_t pos)
{
    if (p.flag == 4)
    {
        outfile << p.infoRead << "\t" << p.flag << "\t*\t0\t0\t*\t*\t0\t0\t";
        outfile << r << "\t" << p.qualRead << endl;
    }
    else
    {
        outfile << p.infoRead << "\t" << p.flag << "\t" << p.nameRead << "\t" << pos << "\t" << "255\t" << p.CIGAR << " \t*\t0\t0\t";
        outfile << r << "\t" << p.qualRead << endl;
    }
}

//
void usage()
{
    cerr << endl
    << "Usage:  randal IndexFileName ReadFileName MapFileName [OPTIONS]" << endl
    << "        IndexFileName           : index file name (from preprocessing step with rand-build)" << endl
    << "        ReadFileName            : read file name (in FASTQ format)" << endl
    << "        MapFileName             : file to store alignment result (in SAM format)" << endl
    << "        [OPTION]            : a list of zero or more optional arguments" << endl
    << "                -mode number    : distance mode (2:hamming distance; 3:edit distance; default 3)" << endl
    << "                -th number      : threshould for distance (integer, >= 0)" << endl
    << "                -att number     : number of attempts for the randomization (integer, > 0)" << endl
    << "                -minws number   : minimal length of common substring between read and reference (integer, > 0, < read length)" << endl
    << "                -maxcdt number  : maximal number of candidates for alignment (integer, > 0)" << endl;
    exit(0);
}

//
void printParameters()
{
    cout << "\nParameters:\n"
         << "Distance mode: " << mode << ", Distance threshold: " << th
         << ", Number of atempts: " << att << ", Minimal LCS: " << minws << ", Maximal alignment: " << maxcdt
         << ", Backward Index File: " << backwardIndexFile << ", Forward Index File: " << forwardIndexFile
         << ", Reference File: " << refFile << ", Read File: " << readFile << ", Map File:" << mapFile << endl;
}

//
void parse_parameters (int argc, char **argv)
{
    char *indexFile;
    // the first three arguments shouldn't start with minus
    if(argv[1][0] == '-' ||argv[2][0] == '-'||argv[3][0] == '-')
    {
        usage();
        return;
    }
    indexFile   = argv[1];
    readFile    = argv[2];
    mapFile     = argv[3];

    char *ref_ext = ".ref";
    char *bw_ext = ".bw";
    char *fw_ext = ".fw";
    int len = strlen(indexFile);
    refFile = new char[len + 4];
    backwardIndexFile = new char[len + 3];
    forwardIndexFile = new char[len + 3];
    strcpy(refFile, indexFile);
    strcat(refFile, ref_ext);
    strcpy(backwardIndexFile, indexFile);
    strcat(backwardIndexFile, bw_ext);
    strcpy(forwardIndexFile, indexFile);
    strcat(forwardIndexFile, fw_ext);

    int argno;
    for (argno = 4; argno < argc - 1; argno++)
    {
        if (argv[argno][0] == '-')
        {
            if (!strcmp (argv[argno], "-mode"))
            {
                if (argno == argc - 1) std::cerr << "Must specify searching mode after -mode" << std::endl;
                mode = atoi(argv[++argno]);
                if ((mode != 1) && (mode != 2) && (mode != 3))
                {
                    usage();
                    return;
                }
            }
            else if (!strcmp (argv[argno], "-th"))
            {
                if (argno == argc - 1) std::cerr << "Must specify threshold after -th" << std::endl;
                th = atoi(argv[++argno]);
                if (th < 0)
                {
                    usage();
                    return;
                }
            }
            else if (!strcmp (argv[argno], "-att"))
            {
                if (argno == argc - 1) std::cerr << "Must specify number of attempts after -att" << std::endl;
                att = atoi(argv[++argno]);
                if (att <= 0)
                {
                    usage();
                    return;
                }
            }
            else if (!strcmp (argv[argno], "-minws"))
            {
                if (argno == argc - 1) std::cerr << "Must specify minimal length of common substring between read and reference after -minws" << std::endl;
                minws = atoi(argv[++argno]);
                if (minws <= 0)
                {
                    usage();
                    return;
                }
            }
            else if (!strcmp (argv[argno], "-maxcdt"))
            {
                if (argno == argc - 1) std::cerr << "Must specify maximal number of candidates for alignment after -maxcdt" << std::endl;
                maxcdt = atoi(argv[++argno]);
                if (maxcdt <= 0)
                {
                    usage();
                    return;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>/**
 ** \file runner/runner.cc
 ** \brief Implementation of runner::Runner.
 */

#include <kernel/uconnection.hh>
#include <runner/runner.hh>

namespace runner
{
  void
  Runner::send_message(const std::string& tag, const std::string& msg)
  {
    // If there is a Channel object with name 'tag', use it.
    rObject chan = lobby_->slot_locate(libport::Symbol(tag), true, true);
    if (chan && is_a(chan, lobby_->slot_get(SYMBOL(Channel))))
    {
      object::objects_type args;
      args.push_back(chan);
      args.push_back(object::rString(new object::String(libport::Symbol(msg))));
      apply(chan->slot_get(SYMBOL(LT_LT_)), SYMBOL(LT_LT_), args);
    }
    else
    {
      object::objects_type args;
      args.push_back(lobby_);
      args.push_back(object::rString(new object::String(libport::Symbol(msg))));
      args.push_back(object::rString(new object::String(libport::Symbol(tag))));
      apply(lobby_->slot_get(SYMBOL(send)), SYMBOL(send), args);
    }
    //UConnection& c = lobby_->value_get().connection;
    //c.send(msg.c_str(), msg.size(), tag.c_str());
  }

  void
  Runner::create_scope_tag()
  {
    scope_tags_.push_back(0);
  }

  scheduler::rTag
  Runner::scope_tag_get() const
  {
    return scope_tags_.back();
  }

  scheduler::rTag
  Runner::scope_tag()
  {
    scheduler::rTag tag = scope_tags_.back();
    if (!tag)
    {
      // Create the tag on demand.
      tag = new scheduler::Tag(libport::Symbol::fresh("<scope tag>"));
      *scope_tags_.rbegin() = tag;
    }
    return tag;
  }

  void
  Runner::cleanup_scope_tag()
  {
    scheduler::rTag tag = scope_tags_.back();
    scope_tags_.pop_back();
    if (tag)
      tag->stop(scheduler_get(), object::void_class);
  }

} // namespace runner
<commit_msg>Create scope tags with the lowest possible priority.<commit_after>/**
 ** \file runner/runner.cc
 ** \brief Implementation of runner::Runner.
 */

#include <kernel/uconnection.hh>
#include <runner/runner.hh>

namespace runner
{
  void
  Runner::send_message(const std::string& tag, const std::string& msg)
  {
    // If there is a Channel object with name 'tag', use it.
    rObject chan = lobby_->slot_locate(libport::Symbol(tag), true, true);
    if (chan && is_a(chan, lobby_->slot_get(SYMBOL(Channel))))
    {
      object::objects_type args;
      args.push_back(chan);
      args.push_back(object::rString(new object::String(libport::Symbol(msg))));
      apply(chan->slot_get(SYMBOL(LT_LT_)), SYMBOL(LT_LT_), args);
    }
    else
    {
      object::objects_type args;
      args.push_back(lobby_);
      args.push_back(object::rString(new object::String(libport::Symbol(msg))));
      args.push_back(object::rString(new object::String(libport::Symbol(tag))));
      apply(lobby_->slot_get(SYMBOL(send)), SYMBOL(send), args);
    }
    //UConnection& c = lobby_->value_get().connection;
    //c.send(msg.c_str(), msg.size(), tag.c_str());
  }

  void
  Runner::create_scope_tag()
  {
    scope_tags_.push_back(0);
  }

  scheduler::rTag
  Runner::scope_tag_get() const
  {
    return scope_tags_.back();
  }

  scheduler::rTag
  Runner::scope_tag()
  {
    scheduler::rTag tag = scope_tags_.back();
    if (!tag)
    {
      // Create the tag on demand. It must have the lowest possible priority to
      // avoid influencing the scheduling algorithm.
      tag = new scheduler::Tag(libport::Symbol::fresh("<scope tag>"));
      tag->prio_set(scheduler::PRIO_MIN);
      *scope_tags_.rbegin() = tag;
    }
    return tag;
  }

  void
  Runner::cleanup_scope_tag()
  {
    scheduler::rTag tag = scope_tags_.back();
    scope_tags_.pop_back();
    if (tag)
      tag->stop(scheduler_get(), object::void_class);
  }

} // namespace runner
<|endoftext|>