<commit_before>/* tntnet.cpp
 * Copyright (C) 2003-2005 Tommi Maekitalo
 *
 * This program 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.1 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "tnt/tntnet.h"
#include "tnt/worker.h"
#include "tnt/listener.h"
#include "tnt/http.h"
#include "tnt/httpreply.h"
#include "tnt/sessionscope.h"

#include <cxxtools/tcpstream.h>
#include <cxxtools/log.h>

#include <config.h>

#ifndef TNTNET_CONF
# define TNTNET_CONF "/etc/tntnet.conf"
#endif

#ifndef TNTNET_PID
# define TNTNET_PID "/var/run/tntnet.pid"
#endif

log_define("tntnet.tntnet")

namespace
{
  void configureDispatcher(tnt::Dispatcher& dis, const tnt::Tntconfig& config)
  {
    typedef tnt::Dispatcher::CompidentType CompidentType;

    const tnt::Tntconfig::config_entries_type& params = config.getConfigValues();

    tnt::Tntconfig::config_entries_type::const_iterator vi;
    for (vi = params.begin(); vi != params.end(); ++vi)
    {
      const tnt::Tntconfig::config_entry_type& v = *vi;
      const tnt::Tntconfig::params_type& args = v.params;
      if (v.key == "MapUrl")
      {
        if (args.size() < 2)
        {
          std::ostringstream msg;
          msg << "invalid number of parameters (" << args.size() << ") in MapUrl";
          throw std::runtime_error(msg.str());
        }

        std::string url = args[0];

        CompidentType ci = CompidentType(args[1]);
        if (args.size() > 2)
        {
          ci.setPathInfo(args[2]);
          if (args.size() > 3)
            ci.setArgs(CompidentType::args_type(args.begin() + 3, args.end()));
        }

        dis.addUrlMapEntry(std::string(), url, ci);
      }
      else if (v.key == "VMapUrl")
      {
        if (args.size() < 3)
        {
          std::ostringstream msg;
          msg << "invalid number of parameters (" << args.size() << ") in VMapUrl";
          throw std::runtime_error(msg.str());
        }

        std::string vhost = args[0];
        std::string url = args[1];

        CompidentType ci = CompidentType(args[2]);
        if (args.size() > 3)
        {
          ci.setPathInfo(args[3]);
          if (args.size() > 4)
            ci.setArgs(CompidentType::args_type(args.begin() + 4, args.end()));
        }

        dis.addUrlMapEntry(vhost, url, ci);
      }
    }
  }
}

namespace tnt
{
  ////////////////////////////////////////////////////////////////////////
  // Tntnet
  //
  Tntnet::Tntnet()
    : pollerthread(queue),
      minthreads(5),
      maxthreads(100),
      threadstartdelay(10),
      timersleep(10)
  { }

  bool Tntnet::stop = false;

  void Tntnet::init(const Tntconfig& config)
  {
    minthreads = config.getValue<unsigned>("MinThreads", minthreads);
    maxthreads = config.getValue<unsigned>("MaxThreads", maxthreads);
    threadstartdelay = config.getValue<unsigned>("ThreadStartDelay", threadstartdelay);
    timersleep = config.getValue<unsigned>("TimerSleep", timersleep);
    Worker::setMaxRequestTime(config.getValue<unsigned>("MaxRequestTime", Worker::getMaxRequestTime()));
    Worker::setEnableCompression(config.getBoolValue("EnableCompression", Worker::getEnableCompression()));
    queue.setCapacity(config.getValue<unsigned>("QueueSize", queue.getCapacity()));
    Sessionscope::setDefaultTimeout(config.getValue<unsigned>("SessionTimeout", Sessionscope::getDefaultTimeout()));
    Listener::setBacklog(config.getValue<int>("ListenBacklog", Listener::getBacklog()));
    Listener::setListenRetry(config.getValue<int>("ListenRetry", Listener::getListenRetry()));
    Dispatcher::setMaxUrlMapCache(config.getValue<unsigned>("MaxUrlMapCache", Dispatcher::getMaxUrlMapCache()));

    Tntconfig::config_entries_type configSetEnv;
    config.getConfigValues("SetEnv", configSetEnv);
    for (Tntconfig::config_entries_type::const_iterator it = configSetEnv.begin();
         it != configSetEnv.end(); ++it)
    {
      if (it->params.size() >= 2)
      {
#ifdef HAVE_SETENV
        log_debug("setenv " << it->params[0] << "=\"" << it->params[1] << '"');
        ::setenv(it->params[0].c_str(), it->params[1].c_str(), 1);
#else
        std::string name  = it->params[0];
        std::string value = it->params[1];

        char* env = new char[name.size() + value.size() + 2];
        name.copy(env, name.size());
        env[name.size()] = '=';
        value.copy(env + name.size() + 1, value.size());
        env[name.size() + value.size() + 1] = '\0';

        log_debug("putenv(" << env << ')');
        ::putenv(env);
#endif
      }
    }

    configureDispatcher(dispatcher, config);

    // configure worker (static)
    Comploader::configure(config);

    // configure http
    HttpRequest::setMaxRequestSize(
      config.getValue("MaxRequestSize", HttpRequest::getMaxRequestSize()));
    Job::setSocketReadTimeout(
      config.getValue("SocketReadTimeout", Job::getSocketReadTimeout()));
    Job::setSocketWriteTimeout(
      config.getValue("SocketWriteTimeout", Job::getSocketWriteTimeout()));
    Job::setKeepAliveMax(
      config.getValue("KeepAliveMax", Job::getKeepAliveMax()));
    Job::setSocketBufferSize(
      config.getValue("BufferSize", Job::getSocketBufferSize()));
    HttpReply::setMinCompressSize(
      config.getValue("MinCompressSize", HttpReply::getMinCompressSize()));
    HttpReply::setKeepAliveTimeout(
      config.getValue("KeepAliveTimeout", HttpReply::getKeepAliveTimeout()));
    HttpReply::setDefaultContentType(
      config.getValue("DefaultContentType", HttpReply::getDefaultContentType()));

    // initialize listeners
    Tntconfig::config_entries_type configListen;
    config.getConfigValues("Listen", configListen);

    for (Tntconfig::config_entries_type::const_iterator it = configListen.begin();
         it != configListen.end(); ++it)
    {
      if (it->params.empty())
        throw std::runtime_error("empty Listen-entry");

      unsigned short int port = 80;
      if (it->params.size() >= 2)
      {
        std::istringstream p(it->params[1]);
        p >> port;
        if (!p)
        {
          std::ostringstream msg;
          msg << "invalid port " << it->params[1];
          throw std::runtime_error(msg.str());
        }
      }

      std::string ip(it->params[0]);

      listen(ip, port);
    }

#ifdef USE_SSL
    // initialize ssl-listener
    Tntconfig::config_entries_type configSslListen;
    config.getConfigValues("SslListen", configSslListen);
    std::string defaultCertificateFile = config.getValue("SslCertificate");
    std::string defaultCertificateKey = config.getValue("SslKey");

    for (Tntconfig::config_entries_type::const_iterator it = configSslListen.begin();
         it != configSslListen.end(); ++it)
    {
      if (it->params.empty())
        throw std::runtime_error("empty SslListen-entry");

      unsigned short int port = 443;
      if (it->params.size() >= 2)
      {
        std::istringstream p(it->params[1]);
        p >> port;
        if (!p)
        {
          std::ostringstream msg;
          msg << "invalid port " << it->params[1];
          throw std::runtime_error(msg.str());
        }
      }

      std::string certificateFile =
        it->params.size() >= 3 ? it->params[2]
                               : defaultCertificateFile;
      std::string keyFile =
        it->params.size() >= 4 ? it->params[3] :
        it->params.size() >= 3 ? it->params[2] : defaultCertificateKey;

      if (certificateFile.empty())
        throw std::runtime_error("Ssl-certificate not configured");

      std::string ip(it->params[0]);

      sslListen(certificateFile, keyFile, ip, port);
    }
#endif // USE_SSL
  }

  void Tntnet::listen(const std::string& ip, unsigned short int port)
  {
    log_debug("listen on ip " << ip << " port " << port);
    listeners.insert(new tnt::Listener(ip, port, queue));
  }

  void Tntnet::sslListen(const std::string& certificateFile, const std::string& keyFile, const std::string& ip, unsigned short int port)
  {
#ifdef USE_SSL
    log_debug("listen on ip " << ip << " port " << port << " (ssl)");
    listeners.insert(new Ssllistener(certificateFile.c_str(),
        keyFile.c_str(), ip, port, queue));
#else
    log_error("cannot add ssl listener - ssl is not compiled into tntnet");
#endif // USE_SSL
  }

  void Tntnet::run()
  {
    log_debug("worker-process");

    if (listeners.empty())
    {
      unsigned short int port = (getuid() == 0 ? 80 : 8000);
      log_info("no listeners defined - using ip 0.0.0.0 port " << port);
      listeners.insert(new tnt::Listener("0.0.0.0", port, queue));
    }
    else
      log_debug(listeners.size() << " listeners");

    if (listeners.size() >= minthreads)
    {
      log_warn("at least one more worker than listeners needed - set MinThreads to "
        << listeners.size() + 1);
      minthreads = listeners.size() + 1;
    }

    if (maxthreads < minthreads)
    {
      log_warn("MaxThreads < MinThreads - set MaxThreads = MinThreads = " << minthreads);
      maxthreads = minthreads;
    }

    // initialize worker-process
    // create worker-threads
    log_info("create " << minthreads << " worker threads");
    for (unsigned i = 0; i < minthreads; ++i)
    {
      log_debug("create worker " << i);
      Worker* s = new Worker(*this);
      s->create();
    }

    // create poller-thread
    log_debug("start poller thread");
    pollerthread.create();

    log_debug("start timer thread");
    cxxtools::MethodThread<Tntnet, cxxtools::AttachedThread> timerThread(*this, &Tntnet::timerTask);
    timerThread.create();

    // mainloop
    cxxtools::Mutex mutex;
    while (!stop)
    {
      {
        cxxtools::MutexLock lock(mutex);
        queue.noWaitThreads.wait(lock);
      }

      if (stop)
        break;

      if (Worker::getCountThreads() < maxthreads)
      {
        log_info("create workerthread");
        Worker* s = new Worker(*this);
        s->create();
      }
      else
        log_info("max worker-threadcount " << maxthreads << " reached");

      if (threadstartdelay > 0)
        usleep(threadstartdelay * 1000);
    }

    log_warn("stopping Tntnet");

    // join-loop
    while (!listeners.empty())
    {
      listeners_type::value_type s = *listeners.begin();
      log_debug("remove listener from listener-list");
      listeners.erase(s);

      log_debug("request listener to stop");
      s->doStop();

      delete s;

      log_debug("listener stopped");
    }

    log_info("listeners stopped");
  }

  void Tntnet::setMinThreads(unsigned n)
  {
    if (listeners.size() >= n)
    {
      log_warn("at least one more worker than listeners needed - set MinThreads to "
        << listeners.size() + 1);
      minthreads = listeners.size() + 1;
    }
    else
      minthreads = n;

  }

  void Tntnet::timerTask()
  {
    log_debug("timer thread");

    while (!stop)
    {
      sleep(timersleep);
      getScopemanager().checkSessionTimeout();
      Worker::timer();
    }

    log_warn("stopping Tntnet");

    queue.noWaitThreads.signal();
    minthreads = maxthreads = 0;
    pollerthread.doStop();
  }

  void Tntnet::shutdown()
  {
    stop = true;
  }
}
<commit_msg>reset stop flag before starting threads<commit_after>/* tntnet.cpp
 * Copyright (C) 2003-2005 Tommi Maekitalo
 *
 * This program 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.1 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 */

#include "tnt/tntnet.h"
#include "tnt/worker.h"
#include "tnt/listener.h"
#include "tnt/http.h"
#include "tnt/httpreply.h"
#include "tnt/sessionscope.h"

#include <cxxtools/tcpstream.h>
#include <cxxtools/log.h>

#include <config.h>

#ifndef TNTNET_CONF
# define TNTNET_CONF "/etc/tntnet.conf"
#endif

#ifndef TNTNET_PID
# define TNTNET_PID "/var/run/tntnet.pid"
#endif

log_define("tntnet.tntnet")

namespace
{
  void configureDispatcher(tnt::Dispatcher& dis, const tnt::Tntconfig& config)
  {
    typedef tnt::Dispatcher::CompidentType CompidentType;

    const tnt::Tntconfig::config_entries_type& params = config.getConfigValues();

    tnt::Tntconfig::config_entries_type::const_iterator vi;
    for (vi = params.begin(); vi != params.end(); ++vi)
    {
      const tnt::Tntconfig::config_entry_type& v = *vi;
      const tnt::Tntconfig::params_type& args = v.params;
      if (v.key == "MapUrl")
      {
        if (args.size() < 2)
        {
          std::ostringstream msg;
          msg << "invalid number of parameters (" << args.size() << ") in MapUrl";
          throw std::runtime_error(msg.str());
        }

        std::string url = args[0];

        CompidentType ci = CompidentType(args[1]);
        if (args.size() > 2)
        {
          ci.setPathInfo(args[2]);
          if (args.size() > 3)
            ci.setArgs(CompidentType::args_type(args.begin() + 3, args.end()));
        }

        dis.addUrlMapEntry(std::string(), url, ci);
      }
      else if (v.key == "VMapUrl")
      {
        if (args.size() < 3)
        {
          std::ostringstream msg;
          msg << "invalid number of parameters (" << args.size() << ") in VMapUrl";
          throw std::runtime_error(msg.str());
        }

        std::string vhost = args[0];
        std::string url = args[1];

        CompidentType ci = CompidentType(args[2]);
        if (args.size() > 3)
        {
          ci.setPathInfo(args[3]);
          if (args.size() > 4)
            ci.setArgs(CompidentType::args_type(args.begin() + 4, args.end()));
        }

        dis.addUrlMapEntry(vhost, url, ci);
      }
    }
  }
}

namespace tnt
{
  ////////////////////////////////////////////////////////////////////////
  // Tntnet
  //
  Tntnet::Tntnet()
    : pollerthread(queue),
      minthreads(5),
      maxthreads(100),
      threadstartdelay(10),
      timersleep(10)
  { }

  bool Tntnet::stop = false;

  void Tntnet::init(const Tntconfig& config)
  {
    minthreads = config.getValue<unsigned>("MinThreads", minthreads);
    maxthreads = config.getValue<unsigned>("MaxThreads", maxthreads);
    threadstartdelay = config.getValue<unsigned>("ThreadStartDelay", threadstartdelay);
    timersleep = config.getValue<unsigned>("TimerSleep", timersleep);
    Worker::setMaxRequestTime(config.getValue<unsigned>("MaxRequestTime", Worker::getMaxRequestTime()));
    Worker::setEnableCompression(config.getBoolValue("EnableCompression", Worker::getEnableCompression()));
    queue.setCapacity(config.getValue<unsigned>("QueueSize", queue.getCapacity()));
    Sessionscope::setDefaultTimeout(config.getValue<unsigned>("SessionTimeout", Sessionscope::getDefaultTimeout()));
    Listener::setBacklog(config.getValue<int>("ListenBacklog", Listener::getBacklog()));
    Listener::setListenRetry(config.getValue<int>("ListenRetry", Listener::getListenRetry()));
    Dispatcher::setMaxUrlMapCache(config.getValue<unsigned>("MaxUrlMapCache", Dispatcher::getMaxUrlMapCache()));

    Tntconfig::config_entries_type configSetEnv;
    config.getConfigValues("SetEnv", configSetEnv);
    for (Tntconfig::config_entries_type::const_iterator it = configSetEnv.begin();
         it != configSetEnv.end(); ++it)
    {
      if (it->params.size() >= 2)
      {
#ifdef HAVE_SETENV
        log_debug("setenv " << it->params[0] << "=\"" << it->params[1] << '"');
        ::setenv(it->params[0].c_str(), it->params[1].c_str(), 1);
#else
        std::string name  = it->params[0];
        std::string value = it->params[1];

        char* env = new char[name.size() + value.size() + 2];
        name.copy(env, name.size());
        env[name.size()] = '=';
        value.copy(env + name.size() + 1, value.size());
        env[name.size() + value.size() + 1] = '\0';

        log_debug("putenv(" << env << ')');
        ::putenv(env);
#endif
      }
    }

    configureDispatcher(dispatcher, config);

    // configure worker (static)
    Comploader::configure(config);

    // configure http
    HttpRequest::setMaxRequestSize(
      config.getValue("MaxRequestSize", HttpRequest::getMaxRequestSize()));
    Job::setSocketReadTimeout(
      config.getValue("SocketReadTimeout", Job::getSocketReadTimeout()));
    Job::setSocketWriteTimeout(
      config.getValue("SocketWriteTimeout", Job::getSocketWriteTimeout()));
    Job::setKeepAliveMax(
      config.getValue("KeepAliveMax", Job::getKeepAliveMax()));
    Job::setSocketBufferSize(
      config.getValue("BufferSize", Job::getSocketBufferSize()));
    HttpReply::setMinCompressSize(
      config.getValue("MinCompressSize", HttpReply::getMinCompressSize()));
    HttpReply::setKeepAliveTimeout(
      config.getValue("KeepAliveTimeout", HttpReply::getKeepAliveTimeout()));
    HttpReply::setDefaultContentType(
      config.getValue("DefaultContentType", HttpReply::getDefaultContentType()));

    // initialize listeners
    Tntconfig::config_entries_type configListen;
    config.getConfigValues("Listen", configListen);

    for (Tntconfig::config_entries_type::const_iterator it = configListen.begin();
         it != configListen.end(); ++it)
    {
      if (it->params.empty())
        throw std::runtime_error("empty Listen-entry");

      unsigned short int port = 80;
      if (it->params.size() >= 2)
      {
        std::istringstream p(it->params[1]);
        p >> port;
        if (!p)
        {
          std::ostringstream msg;
          msg << "invalid port " << it->params[1];
          throw std::runtime_error(msg.str());
        }
      }

      std::string ip(it->params[0]);

      listen(ip, port);
    }

#ifdef USE_SSL
    // initialize ssl-listener
    Tntconfig::config_entries_type configSslListen;
    config.getConfigValues("SslListen", configSslListen);
    std::string defaultCertificateFile = config.getValue("SslCertificate");
    std::string defaultCertificateKey = config.getValue("SslKey");

    for (Tntconfig::config_entries_type::const_iterator it = configSslListen.begin();
         it != configSslListen.end(); ++it)
    {
      if (it->params.empty())
        throw std::runtime_error("empty SslListen-entry");

      unsigned short int port = 443;
      if (it->params.size() >= 2)
      {
        std::istringstream p(it->params[1]);
        p >> port;
        if (!p)
        {
          std::ostringstream msg;
          msg << "invalid port " << it->params[1];
          throw std::runtime_error(msg.str());
        }
      }

      std::string certificateFile =
        it->params.size() >= 3 ? it->params[2]
                               : defaultCertificateFile;
      std::string keyFile =
        it->params.size() >= 4 ? it->params[3] :
        it->params.size() >= 3 ? it->params[2] : defaultCertificateKey;

      if (certificateFile.empty())
        throw std::runtime_error("Ssl-certificate not configured");

      std::string ip(it->params[0]);

      sslListen(certificateFile, keyFile, ip, port);
    }
#endif // USE_SSL
  }

  void Tntnet::listen(const std::string& ip, unsigned short int port)
  {
    log_debug("listen on ip " << ip << " port " << port);
    listeners.insert(new tnt::Listener(ip, port, queue));
  }

  void Tntnet::sslListen(const std::string& certificateFile, const std::string& keyFile, const std::string& ip, unsigned short int port)
  {
#ifdef USE_SSL
    log_debug("listen on ip " << ip << " port " << port << " (ssl)");
    listeners.insert(new Ssllistener(certificateFile.c_str(),
        keyFile.c_str(), ip, port, queue));
#else
    log_error("cannot add ssl listener - ssl is not compiled into tntnet");
#endif // USE_SSL
  }

  void Tntnet::run()
  {
    log_debug("worker-process");

    stop = false;

    if (listeners.empty())
    {
      unsigned short int port = (getuid() == 0 ? 80 : 8000);
      log_info("no listeners defined - using ip 0.0.0.0 port " << port);
      listeners.insert(new tnt::Listener("0.0.0.0", port, queue));
    }
    else
      log_debug(listeners.size() << " listeners");

    if (listeners.size() >= minthreads)
    {
      log_warn("at least one more worker than listeners needed - set MinThreads to "
        << listeners.size() + 1);
      minthreads = listeners.size() + 1;
    }

    if (maxthreads < minthreads)
    {
      log_warn("MaxThreads < MinThreads - set MaxThreads = MinThreads = " << minthreads);
      maxthreads = minthreads;
    }

    // initialize worker-process
    // create worker-threads
    log_info("create " << minthreads << " worker threads");
    for (unsigned i = 0; i < minthreads; ++i)
    {
      log_debug("create worker " << i);
      Worker* s = new Worker(*this);
      s->create();
    }

    // create poller-thread
    log_debug("start poller thread");
    pollerthread.create();

    log_debug("start timer thread");
    cxxtools::MethodThread<Tntnet, cxxtools::AttachedThread> timerThread(*this, &Tntnet::timerTask);
    timerThread.create();

    // mainloop
    cxxtools::Mutex mutex;
    while (!stop)
    {
      {
        cxxtools::MutexLock lock(mutex);
        queue.noWaitThreads.wait(lock);
      }

      if (stop)
        break;

      if (Worker::getCountThreads() < maxthreads)
      {
        log_info("create workerthread");
        Worker* s = new Worker(*this);
        s->create();
      }
      else
        log_info("max worker-threadcount " << maxthreads << " reached");

      if (threadstartdelay > 0)
        usleep(threadstartdelay * 1000);
    }

    log_warn("stopping Tntnet");

    // join-loop
    while (!listeners.empty())
    {
      listeners_type::value_type s = *listeners.begin();
      log_debug("remove listener from listener-list");
      listeners.erase(s);

      log_debug("request listener to stop");
      s->doStop();

      delete s;

      log_debug("listener stopped");
    }

    log_info("listeners stopped");
  }

  void Tntnet::setMinThreads(unsigned n)
  {
    if (listeners.size() >= n)
    {
      log_warn("at least one more worker than listeners needed - set MinThreads to "
        << listeners.size() + 1);
      minthreads = listeners.size() + 1;
    }
    else
      minthreads = n;

  }

  void Tntnet::timerTask()
  {
    log_debug("timer thread");

    while (!stop)
    {
      sleep(timersleep);
      getScopemanager().checkSessionTimeout();
      Worker::timer();
    }

    log_warn("stopping Tntnet");

    queue.noWaitThreads.signal();
    minthreads = maxthreads = 0;
    pollerthread.doStop();
  }

  void Tntnet::shutdown()
  {
    stop = true;
  }
}
<|endoftext|>


<commit_before>#include <Automaton.h>
#include "Atm_teensywave.h"

ATM_CLASSNAME & ATM_CLASSNAME::begin( int attached_pin, int steps, int delay )
{
      const static state_t state_table[] PROGMEM = {
      /*                ON_ENTER    ON_LOOP  ON_EXIT  EVT_COUNTER   EVT_TIMER  EVT_TOGGLE   ELSE */
      /* IDLE     */    ACT_IDLE, ATM_SLEEP,      -1,          -1,         -1,         -1,    -1,
      /* START_SN */   ACT_START,        -1,      -1,          -1,         -1,         -1,  SINE,
      /* SINE     */    ACT_SINE,        -1,      -1,    START_SN,       SINE,   START_SW,    -1,
      /* START_SW */   ACT_START,        -1,      -1,          -1,         -1,         -1,   SAW,
      /* SAW      */     ACT_SAW,        -1,      -1,    START_SW,        SAW,   START_SQ,    -1,
      /* START_SQ */ ACT_STARTSQ,        -1,      -1,          -1,         -1,         -1,  SQON,
      /* SQON     */    ACT_SQON,        -1,      -1,          -1,      SQOFF,         -1,    -1,
      /* SQOFF    */   ACT_SQOFF,        -1,      -1,          -1,       SQON,   START_SN,    -1,
	  };
      table( state_table, ELSE );
      pin = attached_pin;
      _steps = steps;
	  _delay = delay;
      set( timer, delay );
      set( phase, steps ); // 314 steps of 0.02 = 6.28 ( 2 * pi )
      _stepsize = (float) 6.28318 / _steps;
      pinMode( pin, OUTPUT );
	  analogWriteResolution( 12 );
      return *this;
}

int ATM_CLASSNAME::event( int id )
{
  switch ( id ) {
	case EVT_TIMER :
	  return expired( timer );
	case EVT_COUNTER :
	  return expired( phase );
	case EVT_TOGGLE :
	  return signalRead( SIG_TOGGLE );
   }
   return 0;
}

void ATM_CLASSNAME::action( int id )
{
  int val;
  switch ( id ) {
	case ACT_IDLE :
	  analogWrite( pin, 0 );
	  return;
	case ACT_START :
      set( timer, _delay );
	  set( phase, _steps );
	  return;
	case ACT_STARTSQ :
      set( timer, (int) ( _steps * _delay / 2 ) );
	  return;
	case ACT_SINE :
	  val = sin( phase.value * _stepsize ) * 2000.0 + 2050.0;
	  analogWrite( pin, val );
	  decrement( phase );
	  return;
	case ACT_SAW :
	  val = phase.value * 13;
	  analogWrite( pin, val );
	  decrement( phase );
	  return;
	case ACT_SQON :
	  analogWrite( pin, 4095 );
	  return;
	case ACT_SQOFF :
	  analogWrite( pin, 0 );
	  return;
   }
}<commit_msg>Signal now also switches from IDLE to START_SN<commit_after>#include <Automaton.h>
#include "Atm_teensywave.h"

ATM_CLASSNAME & ATM_CLASSNAME::begin( int attached_pin, int steps, int delay )
{
      const static state_t state_table[] PROGMEM = {
      /*                ON_ENTER    ON_LOOP  ON_EXIT  EVT_COUNTER   EVT_TIMER  EVT_TOGGLE   ELSE */
      /* IDLE     */    ACT_IDLE, ATM_SLEEP,      -1,          -1,         -1,   START_SN,    -1,
      /* START_SN */   ACT_START,        -1,      -1,          -1,         -1,         -1,  SINE,
      /* SINE     */    ACT_SINE,        -1,      -1,    START_SN,       SINE,   START_SW,    -1,
      /* START_SW */   ACT_START,        -1,      -1,          -1,         -1,         -1,   SAW,
      /* SAW      */     ACT_SAW,        -1,      -1,    START_SW,        SAW,   START_SQ,    -1,
      /* START_SQ */ ACT_STARTSQ,        -1,      -1,          -1,         -1,         -1,  SQON,
      /* SQON     */    ACT_SQON,        -1,      -1,          -1,      SQOFF,         -1,    -1,
      /* SQOFF    */   ACT_SQOFF,        -1,      -1,          -1,       SQON,   START_SN,    -1,
	  };
      table( state_table, ELSE );
      pin = attached_pin;
      _steps = steps;
	  _delay = delay;
      set( timer, delay );
      set( phase, steps ); // 314 steps of 0.02 = 6.28 ( 2 * pi )
      _stepsize = (float) 6.28318 / _steps;
      pinMode( pin, OUTPUT );
	  analogWriteResolution( 12 );
      return *this;
}

int ATM_CLASSNAME::event( int id )
{
  switch ( id ) {
	case EVT_TIMER :
	  return expired( timer );
	case EVT_COUNTER :
	  return expired( phase );
	case EVT_TOGGLE :
	  return signalRead( SIG_TOGGLE );
   }
   return 0;
}

void ATM_CLASSNAME::action( int id )
{
  int val;
  switch ( id ) {
	case ACT_IDLE :
	  analogWrite( pin, 0 );
	  return;
	case ACT_START :
      set( timer, _delay );
	  set( phase, _steps );
	  return;
	case ACT_STARTSQ :
      set( timer, (int) ( _steps * _delay / 2 ) );
	  return;
	case ACT_SINE :
	  val = sin( phase.value * _stepsize ) * 2000.0 + 2050.0;
	  analogWrite( pin, val );
	  decrement( phase );
	  return;
	case ACT_SAW :
	  val = phase.value * 13;
	  analogWrite( pin, val );
	  decrement( phase );
	  return;
	case ACT_SQON :
	  analogWrite( pin, 4095 );
	  return;
	case ACT_SQOFF :
	  analogWrite( pin, 0 );
	  return;
   }
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct produto{
    char name[65];
    int code;
    char size;
    float price;
};

struct pessoa{
    char cabelo;
    char olhos;
    char sexo;
    int idade;
};

int leitura(struct pessoa *o){
    puts("Informe a cor do cabelo(C-castanho, L-louros, P-pretos):");
    scanf(" %c",&(*o).cabelo);
    puts("Informe a cor dos olhos(C-castanho,A=azuis):");
    scanf(" %c",&(*o).olhos);
    puts("Informe o sexo(M ou F):");
    scanf(" %c",&(*o).sexo);
    do{
        puts("Informe a idade:");
        scanf("%d",&(*o).idade);
    }while((*o).idade<=0);
    return (((*o).olhos=='c')||((*o).olhos=='C'))&&(((*o).cabelo=='P')||((*o).cabelo=='p'));
}

void mostrarCampos(struct produto o){
    printf("\n%s",o.name);
    printf("\n%i",o.code);
    printf("\n%c",o.size);
    printf("\n%.2f\n",o.price);
}

void mostrarCamposex2(struct pessoa o){
    printf("\n%c",o.cabelo);
    printf("\n%c",o.olhos);
    printf("\n%c",o.sexo);
    printf("\n%i\n",o.idade);
}

void ex1(){
    struct produto p[4];
    fflush(stdin);
    gets(p[0].name);
    p[0].code=1337;
    p[0].size='P';
    p[0].price=28.5;
    mostrarCampos(p[0]);
    fflush(stdin);
    gets(p[1].name);
    p[1].code=154;
    p[1].size='G';
    p[1].price=23.5;
    mostrarCampos(p[1]);
    fflush(stdin);
    gets(p[2].name);
    p[2].code=597;
    p[2].size='M';
    p[2].price=27;
    mostrarCampos(p[2]);
    fflush(stdin);
    gets(p[3].name);
    p[3].code=754;
    p[3].size='G';
    p[3].price=2;
    mostrarCampos(p[3]);
}

void ex2(){
    int n,count=0;

    do{
        puts("Informe o numero de pessoas:");
        scanf("%d",&n);
    }while(n<=0);
    struct pessoa p[n];
    for(int x=0;x<n;x++){
        if(leitura(&p[x]))count++;
    }
    for(int x=0;x<n;x++){
        mostrarCamposex2(p[x]);
    }
    printf("%.2f %% das pessoas tem cabelo preto e olhos castanhos",!count?0:count/(float)n*100);
}

int main(){
    int pick;
    do{
        puts("Informe o numero do exercicio 1 ou 2:");
        scanf("%d",&pick);
    }while(pick<1||pick>2);

    switch(pick){
    case 1:
        ex1();
        break;
    case 2:
        ex2();
        break;
    }
    return 0;
}
<commit_msg>Update 14_10_13.cpp<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct produto{
    char name[65];
    int code;
    char size;
    float price;
};

struct pessoa{
    char cabelo;
    char olhos;
    char sexo;
    int idade;
};

int leitura(struct pessoa *o,int *maior,int *f1835){
    puts("Informe a cor do cabelo(C-castanho, L-louros, P-pretos):");
    scanf(" %c",&(*o).cabelo);
    puts("Informe a cor dos olhos(C-castanho,A=azuis):");
    scanf(" %c",&(*o).olhos);
    puts("Informe o sexo(M ou F):");
    scanf(" %c",&(*o).sexo);
    do{
        puts("Informe a idade:");
        scanf("%d",&(*o).idade);
    }while((*o).idade<=0);
    if(!*maior||*maior<(*o).idade)*maior=(*o).idade;
    if(((*o).sexo=='f'||(*o).sexo=='F')&&((*o).idade>17&&(*o).idade<36))*f1835+=1;//notação *int++ não é valida com ponteiros
    return (((*o).olhos=='c')||((*o).olhos=='C'))&&(((*o).cabelo=='P')||((*o).cabelo=='p'));
}

void mostrarCampos(struct produto o){
    printf("\n%s",o.name);
    printf("\n%i",o.code);
    printf("\n%c",o.size);
    printf("\n%.2f\n",o.price);
}
void mostrarCamposex2(struct pessoa o){
    printf("\n%c",o.cabelo);
    printf("\n%c",o.olhos);
    printf("\n%c",o.sexo);
    printf("\n%i\n",o.idade);
}

void ex1(){
    struct produto p[4];
    fflush(stdin);
    gets(p[0].name);
    p[0].code=1337;
    p[0].size='P';
    p[0].price=28.5;
    mostrarCampos(p[0]);
    fflush(stdin);
    gets(p[1].name);
    p[1].code=154;
    p[1].size='G';
    p[1].price=23.5;
    mostrarCampos(p[1]);
    fflush(stdin);
    gets(p[2].name);
    p[2].code=597;
    p[2].size='M';
    p[2].price=27;
    mostrarCampos(p[2]);
    fflush(stdin);
    gets(p[3].name);
    p[3].code=754;
    p[3].size='G';
    p[3].price=2;
    mostrarCampos(p[3]);
}

void ex2(){
    int n,count=0,maior,f1835=0;
    do{
        puts("Informe o numero de pessoas:");
        scanf("%d",&n);
    }while(n<=0);
    struct pessoa p[n];
    for(int x=0;x<n;x++){
        if(leitura(&p[x],&maior,&f1835))count++;
    }
    for(int x=0;x<n;x++){
        mostrarCamposex2(p[x]);
    }
    printf("\nmaior idade: %d\n",maior);
    printf("%d mulheres com idade entre 18 e 35\n",f1835);
    printf("%.2f %% das pessoas tem cabelo preto e olhos castanhos",!count?0:count/(float)n*100);
}

int main(){
    int pick;
    do{
        puts("Informe o numero do exercicio 1 ou 2:");
        scanf("%d",&pick);
    }while(pick<1||pick>2);
    switch(pick){
        case 1:
            ex1();
            break;
        case 2:
            ex2();
            break;
    }
    return 0;
}
<|endoftext|>


<commit_before>// Node definition and implementation for C++ binary tree benchmark program

#include <random>

class Node {
  private:
    static std::uniform_real_distribution<double> generator(0, 1);
    static std::mt19937_64 rng;
    double value;
    Node* leftchild;
    Node* rightchild;
<commit_msg>Progress on bench<commit_after>// Node definition and implementation for C++ binary tree benchmark program
//   Be careful not to compile with optimizations or do_work could get optimized away

#include <random>
#include <unistd.h>
#include "gc.h"
#include "gc_cpp.h"
#include "util.cpp"

#define NULL 0
#define WORK_COST 100

class Node : public gc {
  private:
    static std::uniform_real_distribution<double> generator(0, 1);
    static std::mt19937_64 rng;
    double value;
    Node* leftchild;
    Node* rightchild;
  public:
    Node(void);
    void populate(void);
    void do_work(void);
};

// Class constructor
Node::Node(void) {
  this->value = 0;
  this->leftchild = NULL;
  this->rightchild = NULL;
}

// Populate the tree with random values
void Node::populate(void) {
  this->value = this->generator(rng);
  (this->leftchild) ? (this->leftchild->populate()) : (null_function())
  (this->rightchild) ? (this->rightchild->populate()) : (null_function())
}

// Do computationally expensive work
void Node::do_work(void) {
  usleep(100);
}
<|endoftext|>


<commit_before>#include "../include/grammar.hpp"
#include "../include/production.hpp"
#include <utility>

#include<iostream>

using namespace asparserations;
using namespace grammar;

Grammar::Grammar(const std::string& start)
  : m_end(*this, "_end_", 0), m_accept(*this, "_accept_", 0)
{
  m_start_symbol = &add_nonterminal(start);
  m_accept.add_production("_root_", {m_start_symbol});
}

Grammar::Grammar(Grammar&& old)
  : m_tokens(std::move(old.m_tokens)),
    m_nonterminals(std::move(old.m_nonterminals)),
    m_start_symbol(std::move(old.m_start_symbol)),
    m_end(std::move(old.m_end)),
    m_accept(std::move(old.m_accept))
{
  for(auto& pair : m_tokens) {
    pair.second.m_grammar = this;
  }
  for(auto& pair : m_nonterminals) {
    pair.second.m_grammar = this;
  }
}

Token& Grammar::add_token(const std::string& name)
{
  auto result = m_tokens.emplace(std::piecewise_construct,
                                 std::forward_as_tuple(name),
                                 std::forward_as_tuple(*this,
                                                       name,
                                                       m_tokens.size() + 1));
  Token& tok = result.first->second;
  if(result.second) {
    m_token_vec.push_back(&tok);
  }
  return tok;
}

Nonterminal& Grammar::add_nonterminal(const std::string& name)
{
  auto result = m_nonterminals
    .emplace(std::piecewise_construct, std::forward_as_tuple(name),
	     std::forward_as_tuple(*this, name, m_nonterminals.size() + 1));
  Nonterminal& nt = result.first->second;
  if(result.second) {
    m_nonterminal_vec.push_back(&nt);
  }
  return nt;
}

Token& Grammar::token_at(const std::string& name)
{
  return m_tokens.at(name);
}

const Token& Grammar::token_at(const std::string& name) const
{
  return m_tokens.at(name);
}

Nonterminal& Grammar::nonterminal_at(const std::string& name)
{
  return m_nonterminals.at(name);
}

const Nonterminal& Grammar::nonterminal_at(const std::string& name) const
{
  return m_nonterminals.at(name);
}

const std::vector<Nonterminal*>& Grammar::nonterminals() const
{
  return m_nonterminal_vec;
}

const std::vector<Token*>& Grammar::tokens() const
{
  return m_token_vec;
}

const Nonterminal& Grammar::accept() const
{
  return m_accept;
}

const Token& Grammar::end() const
{
  return m_end;
}

Nonterminal& Grammar::start_symbol()
{
  return *m_start_symbol;
}

const Nonterminal& Grammar::start_symbol() const
{
  return *m_start_symbol;
}

void Grammar::set_start_symbol(Nonterminal* start)
{
  if(start != nullptr && &start->grammar() == this) {
    m_start_symbol = start;
    m_accept.production_at("_root_").set_symbol(0, start);
  }
}

void Grammar::compute_first_sets()
{
  bool needs_update = true;
  while(needs_update) {
    needs_update = false;
    for(auto& pair : m_nonterminals) {
      Grammar::NonterminalImp& nonterminal = pair.second;
      for(const auto& elem : nonterminal.productions()) {
	const Production& production = elem.second;
	bool production_derives_empty_string = true;
	//Repeat until first set does not have empty string or end is reached
	for(const Symbol* symbol : production.symbols()) {
	  for(const Token* first : symbol->first_set()) {
	    auto result = nonterminal.m_first_set.insert(first);
	    if(result.second) {
	      needs_update = true;
	    }
	  }
	  if(!symbol->derives_empty_string()) {
	    production_derives_empty_string = false;
	    break;
	  }
	}
	if(production_derives_empty_string) {
	  nonterminal.m_derives_empty_string = true;
	}
      }
    }
  }
  //Handle accept symbol, which is not in nonterminal map
  if(m_start_symbol != nullptr) {
    m_accept.m_first_set = m_start_symbol->first_set();
    if(m_start_symbol->derives_empty_string()) {
      m_accept.m_first_set.insert(&m_end);
    }
  }
}
<commit_msg>Cleanup<commit_after>#include "../include/grammar.hpp"
#include "../include/production.hpp"
#include <utility>

using namespace asparserations;
using namespace grammar;

Grammar::Grammar(const std::string& start)
  : m_end(*this, "_end_", 0), m_accept(*this, "_accept_", 0)
{
  m_start_symbol = &add_nonterminal(start);
  m_accept.add_production("_root_", {m_start_symbol});
}

Grammar::Grammar(Grammar&& old)
  : m_tokens(std::move(old.m_tokens)),
    m_nonterminals(std::move(old.m_nonterminals)),
    m_start_symbol(std::move(old.m_start_symbol)),
    m_end(std::move(old.m_end)),
    m_accept(std::move(old.m_accept))
{
  for(auto& pair : m_tokens) {
    pair.second.m_grammar = this;
  }
  for(auto& pair : m_nonterminals) {
    pair.second.m_grammar = this;
  }
}

Token& Grammar::add_token(const std::string& name)
{
  auto result = m_tokens.emplace(std::piecewise_construct,
                                 std::forward_as_tuple(name),
                                 std::forward_as_tuple(*this,
                                                       name,
                                                       m_tokens.size() + 1));
  Token& tok = result.first->second;
  if(result.second) {
    m_token_vec.push_back(&tok);
  }
  return tok;
}

Nonterminal& Grammar::add_nonterminal(const std::string& name)
{
  auto result = m_nonterminals
    .emplace(std::piecewise_construct, std::forward_as_tuple(name),
	     std::forward_as_tuple(*this, name, m_nonterminals.size() + 1));
  Nonterminal& nt = result.first->second;
  if(result.second) {
    m_nonterminal_vec.push_back(&nt);
  }
  return nt;
}

Token& Grammar::token_at(const std::string& name)
{
  return m_tokens.at(name);
}

const Token& Grammar::token_at(const std::string& name) const
{
  return m_tokens.at(name);
}

Nonterminal& Grammar::nonterminal_at(const std::string& name)
{
  return m_nonterminals.at(name);
}

const Nonterminal& Grammar::nonterminal_at(const std::string& name) const
{
  return m_nonterminals.at(name);
}

const std::vector<Nonterminal*>& Grammar::nonterminals() const
{
  return m_nonterminal_vec;
}

const std::vector<Token*>& Grammar::tokens() const
{
  return m_token_vec;
}

const Nonterminal& Grammar::accept() const
{
  return m_accept;
}

const Token& Grammar::end() const
{
  return m_end;
}

Nonterminal& Grammar::start_symbol()
{
  return *m_start_symbol;
}

const Nonterminal& Grammar::start_symbol() const
{
  return *m_start_symbol;
}

void Grammar::set_start_symbol(Nonterminal* start)
{
  if(start != nullptr && &start->grammar() == this) {
    m_start_symbol = start;
    m_accept.production_at("_root_").set_symbol(0, start);
  }
}

void Grammar::compute_first_sets()
{
  bool needs_update = true;
  while(needs_update) {
    needs_update = false;
    for(auto& pair : m_nonterminals) {
      Grammar::NonterminalImp& nonterminal = pair.second;
      for(const auto& elem : nonterminal.productions()) {
        const Production& production = elem.second;
        bool production_derives_empty_string = true;
        // Repeat until first set does not have empty string or end is reached
        for(const Symbol* symbol : production.symbols()) {
          for(const Token* first : symbol->first_set()) {
            auto result = nonterminal.m_first_set.insert(first);
            if(result.second) {
              needs_update = true;
            }
          }
          if(!symbol->derives_empty_string()) {
            production_derives_empty_string = false;
            break;
          }
        }
        if(production_derives_empty_string) {
          nonterminal.m_derives_empty_string = true;
        }
      }
    }
  }
  //Handle accept symbol, which is not in nonterminal map
  if(m_start_symbol != nullptr) {
    m_accept.m_first_set = m_start_symbol->first_set();
    if(m_start_symbol->derives_empty_string()) {
      m_accept.m_first_set.insert(&m_end);
    }
  }
}
<|endoftext|>


<commit_before>/* Copyright 2012-2013 Peter Goodman, all rights reserved. */
/*
 * state.cc
 *
 *  Created on: 2012-11-19
 *      Author: pag
 *     Version: $Id$
 */

#include "granary/globals.h"
#include "granary/state.h"

extern "C" {

    /// Get access to the CPU-private state.
    extern granary::cpu_state **kernel_get_cpu_state(granary::cpu_state *[]);

    /// Used to run a function on each CPU.
    extern void kernel_run_on_each_cpu(void (*func)(void));

    /// Call a function where all CPUs are synchronised.
    void kernel_run_synchronised(void (*func)(void));

    /// Mark a page as being only readable.
    void kernel_make_page_read_only(void *addr);
}

namespace granary {

    enum {
        MAX_NUM_CPUS = 256
    };

    /// Manually manage our own per-cpu state.
    cpu_state *CPU_STATES[MAX_NUM_CPUS] = {nullptr};

#if CONFIG_CHECK_CPU_ACCESS_SAFE
    /// Check that it's safe to access CPU-private state.
    __attribute__((noinline))
    void check_cpu_access_safety(void) {
        const eflags flags = granary_load_flags();
        if(flags.interrupt) {
            granary_break_on_curiosity();
        }
    }
#endif

    extern "C" uint64_t *granary_get_private_stack_top(void)
    {
#if CONFIG_CHECK_CPU_ACCESS_SAFE
        check_cpu_access_safety();
#endif
        return (uint64_t *) &((*kernel_get_cpu_state(CPU_STATES))->percpu_stack.top);
    }

    namespace detail {
        struct dummy_thread_state : public client::thread_state {
            uint64_t dummy_val;
        };
    }

    /// Figure out the size of the CPU state.
    enum {
        DUMMY_THREAD_STATE_SIZE = sizeof(detail::dummy_thread_state),
        ALIGNED_THREAD_STATE_SIZE = sizeof(granary::thread_state)
                                  + ALIGN_TO(sizeof(granary::thread_state), 8),
        THREAD_STATE_SIZE = (sizeof(uint64_t) == DUMMY_THREAD_STATE_SIZE)
                          ? 0
                          : ALIGNED_THREAD_STATE_SIZE
    };

    /// Gets a handle to the current CPU state.
    cpu_state_handle::cpu_state_handle(void) throw()
        : state(*kernel_get_cpu_state(CPU_STATES))
    { }

    /// Represents CPU state that is actually allocated and has two poisoned
    /// pages around it.
    struct poison {
        char poison[PAGE_SIZE];
    } __attribute__((packed, aligned(CONFIG_MEMORY_PAGE_SIZE)));

    struct poisoned_cpu_state {
        poison before;
        cpu_state state;
        poison after;
    } __attribute__((aligned(CONFIG_MEMORY_PAGE_SIZE)));

    struct unaligned_cpu_state {
        char mem[sizeof(poisoned_cpu_state) + CONFIG_MEMORY_PAGE_SIZE];
    };

    /// Allocate and initialise state for each CPU.
    static void alloc_cpu_state(void) {
        cpu_state **state_ptr(kernel_get_cpu_state(CPU_STATES));
        unaligned_cpu_state *state_ptr(
            allocate_memory<unaligned_cpu_state>());
        uintptr_t state_addr(reinterpret_cast<uintptr_t>(state_ptr));
        poisoned_cpu_state *poisoned_state(unsafe_cast<poisoned_cpu_state *>(
            state_addr + ALIGN_TO(state_addr, CONFIG_MEMORY_PAGE_SIZE)));

        *state_ptr = &(poisoned_state->state);

#if CONFIG_HANDLE_INTERRUPTS || CONFIG_INSTRUMENT_HOST
        // Get a copy of the native IDTR.
        get_idtr(&(poisoned_state->state.native_idtr));
#endif

#if CONFIG_INSTRUMENT_HOST
        /// Get a copy of the native MSR_LSTAR model-specific register.
        poisoned_state->state.native_msr_lstar = get_msr(MSR_LSTAR);
#endif
    }

    /// Initialise the CPU state.
    void cpu_state::init_early(void) throw() {
        kernel_run_on_each_cpu(alloc_cpu_state);
    }

    /// Initialise the IDTR and MSR_LSTAR for each CPU.
    static void set_percpu(void) {
        cpu_state_handle cpu;

#if CONFIG_HANDLE_INTERRUPTS || CONFIG_INSTRUMENT_HOST
        set_idtr(&(cpu->idtr));
#endif

#if CONFIG_INSTRUMENT_HOST
        set_msr(MSR_LSTAR, cpu->msr_lstar);
#endif

        UNUSED(cpu);
    }

    void cpu_state::init_late(void) throw() {
        eflags flags;

        enum {
            NEG_OFFSET = offsetof(poisoned_cpu_state, state),
            POS_OFFSET = offsetof(poisoned_cpu_state, after) - NEG_OFFSET
        };

        for(unsigned i(0); i < MAX_NUM_CPUS; ++i) {

            if(!CPU_STATES[i]) {
                continue;
            }

            // Page protect the poisoned pages around the CPU state.
            kernel_make_page_read_only(
                unsafe_cast<char *>(CPU_STATES[i]) - NEG_OFFSET);
            kernel_make_page_read_only(
                unsafe_cast<char *>(CPU_STATES[i]) + POS_OFFSET);

#if CONFIG_HANDLE_INTERRUPTS || CONFIG_INSTRUMENT_HOST
#   if CONFIG_ENABLE_INTERRUPT_DELAY
            // Allocate space for interrupt delay handlers.
            CPU_STATES[i]->interrupt_delay_handler = reinterpret_cast<app_pc>(
                global_state::FRAGMENT_ALLOCATOR-> \
                    allocate_untyped(16, INTERRUPT_DELAY_CODE_SIZE));
#   endif
            // Create this CPUs IDT and vector entry points.
            flags = granary_disable_interrupts();
            {
                cpu_state_handle cpu;
                cpu.free_transient_allocators();
                CPU_STATES[i]->idtr = create_idt(CPU_STATES[i]->native_idtr);
            }
            granary_store_flags(flags);
#endif
#if CONFIG_INSTRUMENT_HOST
            // Create this CPUs SYSCALL entry point.
            flags = granary_disable_interrupts();
            {
                cpu_state_handle cpu;
                cpu.free_transient_allocators();
                CPU_STATES[i]->msr_lstar = create_syscall_entrypoint(
                    CPU_STATES[i]->native_msr_lstar);
            }
            granary_store_flags(flags);
#endif

            // Page protect the IDTs.
            kernel_make_page_read_only(CPU_STATES[i]->idtr.base);
        }

        kernel_run_on_each_cpu(set_percpu);

        // Performed initialisation, where all CPUs are first synchronised.
        if(should_init_sync()) {
            kernel_run_synchronised(&init_sync);
        }

        UNUSED(flags);
    }

    /// Note: thread_state_handle::thread_state_handle and ::init are in the
    ///       OS-specific state.cc file.
}
<commit_msg>compiler error fix<commit_after>/* Copyright 2012-2013 Peter Goodman, all rights reserved. */
/*
 * state.cc
 *
 *  Created on: 2012-11-19
 *      Author: pag
 *     Version: $Id$
 */

#include "granary/globals.h"
#include "granary/state.h"

extern "C" {

    /// Get access to the CPU-private state.
    extern granary::cpu_state **kernel_get_cpu_state(granary::cpu_state *[]);

    /// Used to run a function on each CPU.
    extern void kernel_run_on_each_cpu(void (*func)(void));

    /// Call a function where all CPUs are synchronised.
    void kernel_run_synchronised(void (*func)(void));

    /// Mark a page as being only readable.
    void kernel_make_page_read_only(void *addr);
}

namespace granary {

    enum {
        MAX_NUM_CPUS = 256
    };

    /// Manually manage our own per-cpu state.
    cpu_state *CPU_STATES[MAX_NUM_CPUS] = {nullptr};

#if CONFIG_CHECK_CPU_ACCESS_SAFE
    /// Check that it's safe to access CPU-private state.
    __attribute__((noinline))
    void check_cpu_access_safety(void) {
        const eflags flags = granary_load_flags();
        if(flags.interrupt) {
            granary_break_on_curiosity();
        }
    }
#endif

    extern "C" uint64_t *granary_get_private_stack_top(void)
    {
#if CONFIG_CHECK_CPU_ACCESS_SAFE
        check_cpu_access_safety();
#endif
        return (uint64_t *) &((*kernel_get_cpu_state(CPU_STATES))->percpu_stack.top);
    }

    namespace detail {
        struct dummy_thread_state : public client::thread_state {
            uint64_t dummy_val;
        };
    }

    /// Figure out the size of the CPU state.
    enum {
        DUMMY_THREAD_STATE_SIZE = sizeof(detail::dummy_thread_state),
        ALIGNED_THREAD_STATE_SIZE = sizeof(granary::thread_state)
                                  + ALIGN_TO(sizeof(granary::thread_state), 8),
        THREAD_STATE_SIZE = (sizeof(uint64_t) == DUMMY_THREAD_STATE_SIZE)
                          ? 0
                          : ALIGNED_THREAD_STATE_SIZE
    };

    /// Gets a handle to the current CPU state.
    cpu_state_handle::cpu_state_handle(void) throw()
        : state(*kernel_get_cpu_state(CPU_STATES))
    { }

    /// Represents CPU state that is actually allocated and has two poisoned
    /// pages around it.
    struct poison {
        char poison[PAGE_SIZE];
    } __attribute__((packed, aligned(CONFIG_MEMORY_PAGE_SIZE)));

    struct poisoned_cpu_state {
        poison before;
        cpu_state state;
        poison after;
    } __attribute__((aligned(CONFIG_MEMORY_PAGE_SIZE)));

    struct unaligned_cpu_state {
        char mem[sizeof(poisoned_cpu_state) + CONFIG_MEMORY_PAGE_SIZE];
    };

    /// Allocate and initialise state for each CPU.
    static void alloc_cpu_state(void) {
        cpu_state **state_ptr(kernel_get_cpu_state(CPU_STATES));
        unaligned_cpu_state *unaligned_state_ptr(
            allocate_memory<unaligned_cpu_state>());
        uintptr_t state_addr(reinterpret_cast<uintptr_t>(unaligned_state_ptr));
        poisoned_cpu_state *poisoned_state(unsafe_cast<poisoned_cpu_state *>(
            state_addr + ALIGN_TO(state_addr, CONFIG_MEMORY_PAGE_SIZE)));

        *state_ptr = &(poisoned_state->state);

#if CONFIG_HANDLE_INTERRUPTS || CONFIG_INSTRUMENT_HOST
        // Get a copy of the native IDTR.
        get_idtr(&(poisoned_state->state.native_idtr));
#endif

#if CONFIG_INSTRUMENT_HOST
        /// Get a copy of the native MSR_LSTAR model-specific register.
        poisoned_state->state.native_msr_lstar = get_msr(MSR_LSTAR);
#endif
    }

    /// Initialise the CPU state.
    void cpu_state::init_early(void) throw() {
        kernel_run_on_each_cpu(alloc_cpu_state);
    }

    /// Initialise the IDTR and MSR_LSTAR for each CPU.
    static void set_percpu(void) {
        cpu_state_handle cpu;

#if CONFIG_HANDLE_INTERRUPTS || CONFIG_INSTRUMENT_HOST
        set_idtr(&(cpu->idtr));
#endif

#if CONFIG_INSTRUMENT_HOST
        set_msr(MSR_LSTAR, cpu->msr_lstar);
#endif

        UNUSED(cpu);
    }

    void cpu_state::init_late(void) throw() {
        eflags flags;

        enum {
            NEG_OFFSET = offsetof(poisoned_cpu_state, state),
            POS_OFFSET = offsetof(poisoned_cpu_state, after) - NEG_OFFSET
        };

        for(unsigned i(0); i < MAX_NUM_CPUS; ++i) {

            if(!CPU_STATES[i]) {
                continue;
            }

            // Page protect the poisoned pages around the CPU state.
            kernel_make_page_read_only(
                unsafe_cast<char *>(CPU_STATES[i]) - NEG_OFFSET);
            kernel_make_page_read_only(
                unsafe_cast<char *>(CPU_STATES[i]) + POS_OFFSET);

#if CONFIG_HANDLE_INTERRUPTS || CONFIG_INSTRUMENT_HOST
#   if CONFIG_ENABLE_INTERRUPT_DELAY
            // Allocate space for interrupt delay handlers.
            CPU_STATES[i]->interrupt_delay_handler = reinterpret_cast<app_pc>(
                global_state::FRAGMENT_ALLOCATOR-> \
                    allocate_untyped(16, INTERRUPT_DELAY_CODE_SIZE));
#   endif
            // Create this CPUs IDT and vector entry points.
            flags = granary_disable_interrupts();
            {
                cpu_state_handle cpu;
                cpu.free_transient_allocators();
                CPU_STATES[i]->idtr = create_idt(CPU_STATES[i]->native_idtr);
            }
            granary_store_flags(flags);
#endif
#if CONFIG_INSTRUMENT_HOST
            // Create this CPUs SYSCALL entry point.
            flags = granary_disable_interrupts();
            {
                cpu_state_handle cpu;
                cpu.free_transient_allocators();
                CPU_STATES[i]->msr_lstar = create_syscall_entrypoint(
                    CPU_STATES[i]->native_msr_lstar);
            }
            granary_store_flags(flags);
#endif

            // Page protect the IDTs.
            kernel_make_page_read_only(CPU_STATES[i]->idtr.base);
        }

        kernel_run_on_each_cpu(set_percpu);

        // Performed initialisation, where all CPUs are first synchronised.
        if(should_init_sync()) {
            kernel_run_synchronised(&init_sync);
        }

        UNUSED(flags);
    }

    /// Note: thread_state_handle::thread_state_handle and ::init are in the
    ///       OS-specific state.cc file.
}
<|endoftext|>


<commit_before>/*  This file is part of the KDE project.

    Copyright (C) 2010-2011 Harald Sitter <sitter@kde.org>
    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).

    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.1 or 3 of the License.

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

    You should have received a copy of the GNU Lesser General Public License
    along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "phononsrc.h"

#include "streamreader.h"

QT_BEGIN_NAMESPACE

namespace Phonon
{
namespace Gstreamer
{

static GstStaticPadTemplate srctemplate =
       GST_STATIC_PAD_TEMPLATE ("src",
                                GST_PAD_SRC,
                                GST_PAD_ALWAYS,
                                GST_STATIC_CAPS_ANY);

GST_DEBUG_CATEGORY_STATIC (phonon_src_debug);

// PhononSrc args
enum
{
    ARG_0,
    ARG_PHONONSRC
};

static void phonon_src_finalize(GObject *object);

static void phonon_src_set_property(GObject *object, guint prop_id,
                                    const GValue *value, GParamSpec *pspec);
static void phonon_src_get_property(GObject *object, guint prop_id,
                                    GValue *value, GParamSpec *pspec);

static gboolean phonon_src_start(GstBaseSrc *basesrc);
static gboolean phonon_src_stop(GstBaseSrc *basesrc);

static gboolean phonon_src_unlock(GstBaseSrc *basesrc);
static gboolean phonon_src_unlock_stop(GstBaseSrc *basesrc);

static gboolean phonon_src_is_seekable(GstBaseSrc *src);
static gboolean phonon_src_get_size(GstBaseSrc *src, guint64 *size);
static GstFlowReturn phonon_src_create(GstBaseSrc *src, guint64 offset,
                                       guint length, GstBuffer **buffer);

static gboolean register_elements(GstPlugin *plugin)
{
    if (!gst_element_register(plugin, "phononsrc", GST_RANK_NONE, GST_TYPE_PHONON_SRC))
        return FALSE;
    return TRUE;
}

gboolean register_phonon_elements()
{
    gst_plugin_register_static(
        GST_VERSION_MAJOR,
        GST_VERSION_MINOR,
        "phonon-plugins",
        "Private elements of Phonon",
        register_elements,
        PHONON_VERSION_STR,
        "LGPL",
        "phonon",
        "phonon",
        "http://phonon.kde.org");
    return TRUE;
}

static void _do_init(GType filesrc_type)
{
    Q_UNUSED(filesrc_type);
    GST_DEBUG_CATEGORY_INIT (phonon_src_debug, "phononsrc", 0, "QIODevice element");
}

GST_BOILERPLATE_FULL(PhononSrc, phonon_src, GstBaseSrc, GST_TYPE_BASE_SRC, _do_init)

// Register element details
static void phonon_src_base_init(gpointer g_class) {
    GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
    static gchar longname[] = "Phonon Stream Source",
                    klass[] = "Source/File",
              description[] = "Read from a Phonon StreamInterface",
                   author[] = "Nokia Corporation and/or its subsidiary(-ies) <qt-info@nokia.com>";
    GstElementDetails details = GST_ELEMENT_DETAILS (longname,
                                          klass,
                                          description,
                                          author);
    gst_element_class_set_details(gstelement_class, &details);
    gst_element_class_add_pad_template(gstelement_class, gst_static_pad_template_get(&srctemplate));
}

static void phonon_src_class_init (PhononSrcClass *klass)
{
    GObjectClass *gobject_class;
    GstElementClass *gstelement_class;
    GstBaseSrcClass *gstbasesrc_class;

    gobject_class = G_OBJECT_CLASS(klass);
    gstelement_class = GST_ELEMENT_CLASS(klass);
    gstbasesrc_class = GST_BASE_SRC_CLASS(klass);

    gobject_class->set_property = phonon_src_set_property;
    gobject_class->get_property = phonon_src_get_property;

    g_object_class_install_property(gobject_class, ARG_PHONONSRC,
                                    g_param_spec_pointer ("iodevice", "A Phonon StreamReader",
                                                          "A Phonon::GStreamer::StreamReader to read from", GParamFlags(G_PARAM_READWRITE)));

    gobject_class->finalize = GST_DEBUG_FUNCPTR(phonon_src_finalize);

    gstbasesrc_class->start = GST_DEBUG_FUNCPTR(phonon_src_start);
    gstbasesrc_class->stop = GST_DEBUG_FUNCPTR(phonon_src_stop);
    gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR(phonon_src_unlock);
    gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR(phonon_src_unlock_stop);
    gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR(phonon_src_is_seekable);
    gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR(phonon_src_get_size);
    gstbasesrc_class->create = GST_DEBUG_FUNCPTR(phonon_src_create);
}

static void phonon_src_init(PhononSrc *src, PhononSrcClass *g_class)
{
    Q_UNUSED(g_class);
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    src->device = 0;
#endif
}

static void phonon_src_finalize(GObject *object)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    PhononSrc *src;
    src = GST_PHONON_SRC(object);
    delete src->device;
    src->device = 0;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    G_OBJECT_CLASS (parent_class)->finalize(object);
}

#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
static gboolean phonon_src_set_device(PhononSrc *src, StreamReader *device)
{
    GstState state;
    // The element must be stopped in order to do this
    GST_OBJECT_LOCK(src);
    state = GST_STATE(src);

    if (state != GST_STATE_READY && state != GST_STATE_NULL)
        goto wrong_state;

    GST_OBJECT_UNLOCK(src);

    src->device = device;
    g_object_notify(G_OBJECT (src), "iodevice");
    return TRUE;

    // Error
wrong_state:
    {
        //GST_DEBUG_OBJECT (src, "setting location in wrong state");
        GST_OBJECT_UNLOCK (src);
        return FALSE;
    }
}
#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM

static void phonon_src_set_property(GObject *object, guint prop_id, const GValue *value,
                                    GParamSpec *pspec)
{
    PhononSrc *src;
    g_return_if_fail(GST_IS_PHONON_SRC(object));
    src = GST_PHONON_SRC(object);

    switch (prop_id) {
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    case ARG_PHONONSRC:
    {
        StreamReader *dev = (StreamReader*)(g_value_get_pointer(value));
        if (dev)
            phonon_src_set_device(src, dev);
        break;
    }
#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
   default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
}

static void phonon_src_get_property(GObject *object, guint prop_id, GValue *value,
                                    GParamSpec *pspec)
{
    PhononSrc *src;
    g_return_if_fail (GST_IS_PHONON_SRC (object));
    src = GST_PHONON_SRC (object);

    switch (prop_id) {
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    case ARG_PHONONSRC:
        g_value_set_pointer(value, src->device);
        break;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
}

static GstFlowReturn phonon_src_create_read(PhononSrc *src, guint64 offset, guint length,
                                            GstBuffer **buffer)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    Q_ASSERT(src->device);
    if (!src->device)
        return GST_FLOW_ERROR;

    GstBuffer *buf = gst_buffer_new_and_alloc (length);
    GST_BUFFER_SIZE (buf) = length;
    GST_BUFFER_OFFSET (buf) = offset;
    GST_BUFFER_OFFSET_END (buf) = offset + length;

    GstFlowReturn ret = src->device->read(offset, length, (char*)GST_BUFFER_DATA (buf));
//    GST_LOG_OBJECT (src, "Reading %d bytes", length);

    if (ret == GST_FLOW_OK) {
        *buffer = buf;
        return ret;
    } else if (ret == GST_FLOW_UNEXPECTED) {
        return ret;
    }

    gst_mini_object_unref(GST_MINI_OBJECT(buf));
    return GST_FLOW_ERROR;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return GST_FLOW_ERROR;
}

static GstFlowReturn phonon_src_create(GstBaseSrc *basesrc, guint64 offset, guint length, GstBuffer **buffer)
{
    PhononSrc *src = GST_PHONON_SRC (basesrc);
    return phonon_src_create_read (src, offset, length, buffer);
}

static gboolean phonon_src_is_seekable(GstBaseSrc *basesrc)
{
    PhononSrc *src = GST_PHONON_SRC(basesrc);
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    if (src->device)
        return src->device->streamSeekable();
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

static gboolean phonon_src_get_size(GstBaseSrc *basesrc, guint64 *size)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    PhononSrc *src = GST_PHONON_SRC(basesrc);
    if (src->device && src->device->streamSeekable()) {
        *size = src->device->streamSize();
        return true;
    }
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    *size = 0;
    return false;
}

static gboolean phonon_src_unlock(GstBaseSrc *basesrc)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    PhononSrc *src = GST_PHONON_SRC(basesrc);
    src->device->unlock();
    return true;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

static gboolean phonon_src_unlock_stop(GstBaseSrc *basesrc)
{
    Q_UNUSED(basesrc);
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    // Resource locking and unlocking happens onthefly, unlock just wakes our
    // QWaitConditions.
    return true;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

// Necessary to go to READY state
static gboolean phonon_src_start(GstBaseSrc *basesrc)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    // Opening the device is handled by the frontend, still we need to make sure
    // that the streamer is in initial state WRT member variables etc.
    PhononSrc *src = GST_PHONON_SRC(basesrc);
    src->device->start();
    return true;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

static gboolean phonon_src_stop(GstBaseSrc *basesrc)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    // Closing the device is handled by the frontend, we just need to ensure
    // the reader is unlocked and send a final enoughData.
    PhononSrc *src = GST_PHONON_SRC(basesrc);
    src->device->stop();
    return TRUE;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

}
} //namespace Phonon::Gstreamer

QT_END_NAMESPACE
<commit_msg>if you write a cpp gst sink, thenat least use bools :S<commit_after>/*  This file is part of the KDE project.

    Copyright (C) 2010-2011 Harald Sitter <sitter@kde.org>
    Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).

    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.1 or 3 of the License.

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

    You should have received a copy of the GNU Lesser General Public License
    along with this library.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "phononsrc.h"

#include "streamreader.h"

QT_BEGIN_NAMESPACE

namespace Phonon
{
namespace Gstreamer
{

static GstStaticPadTemplate srctemplate =
       GST_STATIC_PAD_TEMPLATE ("src",
                                GST_PAD_SRC,
                                GST_PAD_ALWAYS,
                                GST_STATIC_CAPS_ANY);

GST_DEBUG_CATEGORY_STATIC (phonon_src_debug);

// PhononSrc args
enum
{
    ARG_0,
    ARG_PHONONSRC
};

static void phonon_src_finalize(GObject *object);

static void phonon_src_set_property(GObject *object, guint prop_id,
                                    const GValue *value, GParamSpec *pspec);
static void phonon_src_get_property(GObject *object, guint prop_id,
                                    GValue *value, GParamSpec *pspec);

static gboolean phonon_src_start(GstBaseSrc *basesrc);
static gboolean phonon_src_stop(GstBaseSrc *basesrc);

static gboolean phonon_src_unlock(GstBaseSrc *basesrc);
static gboolean phonon_src_unlock_stop(GstBaseSrc *basesrc);

static gboolean phonon_src_is_seekable(GstBaseSrc *src);
static gboolean phonon_src_get_size(GstBaseSrc *src, guint64 *size);
static GstFlowReturn phonon_src_create(GstBaseSrc *src, guint64 offset,
                                       guint length, GstBuffer **buffer);

static gboolean register_elements(GstPlugin *plugin)
{
    if (!gst_element_register(plugin, "phononsrc", GST_RANK_NONE, GST_TYPE_PHONON_SRC))
        return false;
    return true;
}

gboolean register_phonon_elements()
{
    gst_plugin_register_static(
        GST_VERSION_MAJOR,
        GST_VERSION_MINOR,
        "phonon-plugins",
        "Private elements of Phonon",
        register_elements,
        PHONON_VERSION_STR,
        "LGPL",
        "phonon",
        "phonon",
        "http://phonon.kde.org");
    return true;
}

static void _do_init(GType filesrc_type)
{
    Q_UNUSED(filesrc_type);
    GST_DEBUG_CATEGORY_INIT (phonon_src_debug, "phononsrc", 0, "QIODevice element");
}

GST_BOILERPLATE_FULL(PhononSrc, phonon_src, GstBaseSrc, GST_TYPE_BASE_SRC, _do_init)

// Register element details
static void phonon_src_base_init(gpointer g_class) {
    GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
    static gchar longname[] = "Phonon Stream Source",
                    klass[] = "Source/File",
              description[] = "Read from a Phonon StreamInterface",
                   author[] = "Nokia Corporation and/or its subsidiary(-ies) <qt-info@nokia.com>";
    GstElementDetails details = GST_ELEMENT_DETAILS (longname,
                                          klass,
                                          description,
                                          author);
    gst_element_class_set_details(gstelement_class, &details);
    gst_element_class_add_pad_template(gstelement_class, gst_static_pad_template_get(&srctemplate));
}

static void phonon_src_class_init (PhononSrcClass *klass)
{
    GObjectClass *gobject_class;
    GstElementClass *gstelement_class;
    GstBaseSrcClass *gstbasesrc_class;

    gobject_class = G_OBJECT_CLASS(klass);
    gstelement_class = GST_ELEMENT_CLASS(klass);
    gstbasesrc_class = GST_BASE_SRC_CLASS(klass);

    gobject_class->set_property = phonon_src_set_property;
    gobject_class->get_property = phonon_src_get_property;

    g_object_class_install_property(gobject_class, ARG_PHONONSRC,
                                    g_param_spec_pointer ("iodevice", "A Phonon StreamReader",
                                                          "A Phonon::GStreamer::StreamReader to read from", GParamFlags(G_PARAM_READWRITE)));

    gobject_class->finalize = GST_DEBUG_FUNCPTR(phonon_src_finalize);

    gstbasesrc_class->start = GST_DEBUG_FUNCPTR(phonon_src_start);
    gstbasesrc_class->stop = GST_DEBUG_FUNCPTR(phonon_src_stop);
    gstbasesrc_class->unlock = GST_DEBUG_FUNCPTR(phonon_src_unlock);
    gstbasesrc_class->unlock_stop = GST_DEBUG_FUNCPTR(phonon_src_unlock_stop);
    gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR(phonon_src_is_seekable);
    gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR(phonon_src_get_size);
    gstbasesrc_class->create = GST_DEBUG_FUNCPTR(phonon_src_create);
}

static void phonon_src_init(PhononSrc *src, PhononSrcClass *g_class)
{
    Q_UNUSED(g_class);
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    src->device = 0;
#endif
}

static void phonon_src_finalize(GObject *object)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    PhononSrc *src;
    src = GST_PHONON_SRC(object);
    delete src->device;
    src->device = 0;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    G_OBJECT_CLASS (parent_class)->finalize(object);
}

#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
static gboolean phonon_src_set_device(PhononSrc *src, StreamReader *device)
{
    GstState state;
    // The element must be stopped in order to do this
    GST_OBJECT_LOCK(src);
    state = GST_STATE(src);

    if (state != GST_STATE_READY && state != GST_STATE_NULL)
        goto wrong_state;

    GST_OBJECT_UNLOCK(src);

    src->device = device;
    g_object_notify(G_OBJECT (src), "iodevice");
    return true;

    // Error
wrong_state:
    {
        //GST_DEBUG_OBJECT (src, "setting location in wrong state");
        GST_OBJECT_UNLOCK (src);
        return false;
    }
}
#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM

static void phonon_src_set_property(GObject *object, guint prop_id, const GValue *value,
                                    GParamSpec *pspec)
{
    PhononSrc *src;
    g_return_if_fail(GST_IS_PHONON_SRC(object));
    src = GST_PHONON_SRC(object);

    switch (prop_id) {
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    case ARG_PHONONSRC:
    {
        StreamReader *dev = (StreamReader*)(g_value_get_pointer(value));
        if (dev)
            phonon_src_set_device(src, dev);
        break;
    }
#endif //QT_NO_PHONON_ABSTRACTMEDIASTREAM
   default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
   }
}

static void phonon_src_get_property(GObject *object, guint prop_id, GValue *value,
                                    GParamSpec *pspec)
{
    PhononSrc *src;
    g_return_if_fail (GST_IS_PHONON_SRC (object));
    src = GST_PHONON_SRC (object);

    switch (prop_id) {
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    case ARG_PHONONSRC:
        g_value_set_pointer(value, src->device);
        break;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    default:
        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
        break;
    }
}

static GstFlowReturn phonon_src_create_read(PhononSrc *src, guint64 offset, guint length,
                                            GstBuffer **buffer)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    Q_ASSERT(src->device);
    if (!src->device)
        return GST_FLOW_ERROR;

    GstBuffer *buf = gst_buffer_new_and_alloc (length);
    GST_BUFFER_SIZE (buf) = length;
    GST_BUFFER_OFFSET (buf) = offset;
    GST_BUFFER_OFFSET_END (buf) = offset + length;

    GstFlowReturn ret = src->device->read(offset, length, (char*)GST_BUFFER_DATA (buf));
//    GST_LOG_OBJECT (src, "Reading %d bytes", length);

    if (ret == GST_FLOW_OK) {
        *buffer = buf;
        return ret;
    } else if (ret == GST_FLOW_UNEXPECTED) {
        return ret;
    }

    gst_mini_object_unref(GST_MINI_OBJECT(buf));
    return GST_FLOW_ERROR;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return GST_FLOW_ERROR;
}

static GstFlowReturn phonon_src_create(GstBaseSrc *basesrc, guint64 offset, guint length, GstBuffer **buffer)
{
    PhononSrc *src = GST_PHONON_SRC (basesrc);
    return phonon_src_create_read (src, offset, length, buffer);
}

static gboolean phonon_src_is_seekable(GstBaseSrc *basesrc)
{
    PhononSrc *src = GST_PHONON_SRC(basesrc);
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    if (src->device)
        return src->device->streamSeekable();
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

static gboolean phonon_src_get_size(GstBaseSrc *basesrc, guint64 *size)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    PhononSrc *src = GST_PHONON_SRC(basesrc);
    if (src->device && src->device->streamSeekable()) {
        *size = src->device->streamSize();
        return true;
    }
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    *size = 0;
    return false;
}

static gboolean phonon_src_unlock(GstBaseSrc *basesrc)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    PhononSrc *src = GST_PHONON_SRC(basesrc);
    src->device->unlock();
    return true;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

static gboolean phonon_src_unlock_stop(GstBaseSrc *basesrc)
{
    Q_UNUSED(basesrc);
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    // Resource locking and unlocking happens onthefly, unlock just wakes our
    // QWaitConditions.
    return true;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

// Necessary to go to READY state
static gboolean phonon_src_start(GstBaseSrc *basesrc)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    // Opening the device is handled by the frontend, still we need to make sure
    // that the streamer is in initial state WRT member variables etc.
    PhononSrc *src = GST_PHONON_SRC(basesrc);
    src->device->start();
    return true;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

static gboolean phonon_src_stop(GstBaseSrc *basesrc)
{
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
    // Closing the device is handled by the frontend, we just need to ensure
    // the reader is unlocked and send a final enoughData.
    PhononSrc *src = GST_PHONON_SRC(basesrc);
    src->device->stop();
    return true;
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
    return false;
}

}
} //namespace Phonon::Gstreamer

QT_END_NAMESPACE
<|endoftext|>


<commit_before>/**
 * @author: Jeff Thompson
 * See COPYING for copyright and distribution information.
 */

#ifndef NDN_NAME_HPP
#define NDN_NAME_HPP

#include <vector>
#include <string>
#include "c/name.h"
#include "encoding/binary-xml-wire-format.hpp"

namespace ndn {

class Name {
public:
  class Component {
  public:
    /**
     * Create a new Name::Component with an empty value.
     */
    Component()
    {
    }

    /**
     * Create a new Name::Component, copying the given value.
     * @param value The value byte array.
     */
    Component(const std::vector<unsigned char> &value)
    : value_(value)
    {
    }

    /**
     * Create a new Name::Component, copying the given value.
     * @param value Pointer to the value byte array.
     * @param valueLen Length of value.
     */
    Component(unsigned char *value, unsigned int valueLen)
    : value_(value, value + valueLen)
    {
    }

    /**
     * Set the componentStruct to point to this component, without copying any memory.
     * WARNING: The resulting pointer in componentStruct is invalid after a further use of this object which could reallocate memory.
     * @param componentStruct The C ndn_NameComponent struct to receive the pointer.
     */
    void get(struct ndn_NameComponent &componentStruct) const
    {
      componentStruct.valueLength = value_.size();
      if (value_.size() > 0)
        componentStruct.value = (unsigned char *)&value_[0];
    }

    /**
     * Set this component value by decoding the escapedString between first and last according to the NDN URI Scheme.
     * If the escaped string is "", "." or ".." then return false, which means this component value was not changed, and
     * the component should be skipped in a URI name.
     * @param first Pointer to the beginning of the escaped string
     * @param last Pointer to the first character past the end of the escaped string
     * @return True for success, false if escapedString is not a valid escaped component.
     */
    bool setFromEscapedString(const char *first, const char *last);

    const std::vector<unsigned char> &getValue() const { return value_; }

    /**
     * Set this component to the encoded segment number.
     * @param segment The segment number.
     */
    void setSegment(unsigned long segment);

  private:
    std::vector<unsigned char> value_;
  };

  /**
   * Create a new Name with no components.
   */
  Name() {
  }

  /**
   * Create a new Name, copying the name components.
   * @param components A vector of Component
   */
  Name(const std::vector<Component> &components)
  : components_(components)
  {
  }

  /**
   * Parse the uri according to the NDN URI Scheme and create the name with the components.
   * @param uri The URI string.
   */
  Name(const char *uri)
  {
    set(uri);
  }

  /**
   * Set the nameStruct to point to the components in this name, without copying any memory.
   * WARNING: The resulting pointers in nameStruct are invalid after a further use of this object which could reallocate memory.
   * @param nameStruct A C ndn_Name struct where the components array is already allocated.
   */
  void get(struct ndn_Name &nameStruct) const;

  /**
   * Clear this name, and set the components by copying from the name struct.
   * @param nameStruct A C ndn_Name struct
   */
  void set(const struct ndn_Name &nameStruct);

  /**
   * Parse the uri according to the NDN URI Scheme and set the name with the components.
   * @param uri The URI string.
   */
  void set(const char *uri);

  /**
   * Add a new component, copying from value of length valueLength.
   */
  void addComponent(unsigned char *value, unsigned int valueLength) {
    components_.push_back(Component(value, valueLength));
  }

  /**
   * Clear all the components.
   */
  void clear() {
    components_.clear();
  }

  /**
   * Get the number of components.
   * @return The number of components.
   */
  unsigned int getComponentCount() const {
    return components_.size();
  }

  const Component &getComponent(unsigned int i) const { return components_[i]; }

  /**
   * Encode this name as a URI.
   * @return The encoded URI.
   */
  std::string toUri() const;

  /**
   * @deprecated Use toUri().
   */
  std::string to_uri() const
  {
    return toUri();
  }

  /**
   * Append a component with the encoded segment number.
   * @param segment The segment number.
   */
  void appendSegment(unsigned long segment)
  {
    components_.push_back(Component());
    components_.back().setSegment(segment);
  }

private:
  std::vector<Component> components_;
};

}

#endif

<commit_msg>Added addComponent(vector<unsigned char>)<commit_after>/**
 * @author: Jeff Thompson
 * See COPYING for copyright and distribution information.
 */

#ifndef NDN_NAME_HPP
#define NDN_NAME_HPP

#include <vector>
#include <string>
#include "c/name.h"
#include "encoding/binary-xml-wire-format.hpp"

namespace ndn {

class Name {
public:
  class Component {
  public:
    /**
     * Create a new Name::Component with an empty value.
     */
    Component()
    {
    }

    /**
     * Create a new Name::Component, copying the given value.
     * @param value The value byte array.
     */
    Component(const std::vector<unsigned char> &value)
    : value_(value)
    {
    }

    /**
     * Create a new Name::Component, copying the given value.
     * @param value Pointer to the value byte array.
     * @param valueLen Length of value.
     */
    Component(unsigned char *value, unsigned int valueLen)
    : value_(value, value + valueLen)
    {
    }

    /**
     * Set the componentStruct to point to this component, without copying any memory.
     * WARNING: The resulting pointer in componentStruct is invalid after a further use of this object which could reallocate memory.
     * @param componentStruct The C ndn_NameComponent struct to receive the pointer.
     */
    void get(struct ndn_NameComponent &componentStruct) const
    {
      componentStruct.valueLength = value_.size();
      if (value_.size() > 0)
        componentStruct.value = (unsigned char *)&value_[0];
    }

    /**
     * Set this component value by decoding the escapedString between first and last according to the NDN URI Scheme.
     * If the escaped string is "", "." or ".." then return false, which means this component value was not changed, and
     * the component should be skipped in a URI name.
     * @param first Pointer to the beginning of the escaped string
     * @param last Pointer to the first character past the end of the escaped string
     * @return True for success, false if escapedString is not a valid escaped component.
     */
    bool setFromEscapedString(const char *first, const char *last);

    const std::vector<unsigned char> &getValue() const { return value_; }

    /**
     * Set this component to the encoded segment number.
     * @param segment The segment number.
     */
    void setSegment(unsigned long segment);

  private:
    std::vector<unsigned char> value_;
  };

  /**
   * Create a new Name with no components.
   */
  Name() {
  }

  /**
   * Create a new Name, copying the name components.
   * @param components A vector of Component
   */
  Name(const std::vector<Component> &components)
  : components_(components)
  {
  }

  /**
   * Parse the uri according to the NDN URI Scheme and create the name with the components.
   * @param uri The URI string.
   */
  Name(const char *uri)
  {
    set(uri);
  }

  /**
   * Set the nameStruct to point to the components in this name, without copying any memory.
   * WARNING: The resulting pointers in nameStruct are invalid after a further use of this object which could reallocate memory.
   * @param nameStruct A C ndn_Name struct where the components array is already allocated.
   */
  void get(struct ndn_Name &nameStruct) const;

  /**
   * Clear this name, and set the components by copying from the name struct.
   * @param nameStruct A C ndn_Name struct
   */
  void set(const struct ndn_Name &nameStruct);

  /**
   * Parse the uri according to the NDN URI Scheme and set the name with the components.
   * @param uri The URI string.
   */
  void set(const char *uri);

  /**
   * Add a new component, copying from value of length valueLength.
   */
  void addComponent(unsigned char *value, unsigned int valueLength) {
    components_.push_back(Component(value, valueLength));
  }

  /**
   * Add a new component, copying from value.
   */
  void addComponent(const std::vector<unsigned char> &value) {
    components_.push_back(value);
  }

  /**
   * Clear all the components.
   */
  void clear() {
    components_.clear();
  }

  /**
   * Get the number of components.
   * @return The number of components.
   */
  unsigned int getComponentCount() const {
    return components_.size();
  }

  const Component &getComponent(unsigned int i) const { return components_[i]; }

  /**
   * Encode this name as a URI.
   * @return The encoded URI.
   */
  std::string toUri() const;

  /**
   * @deprecated Use toUri().
   */
  std::string to_uri() const
  {
    return toUri();
  }

  /**
   * Append a component with the encoded segment number.
   * @param segment The segment number.
   */
  void appendSegment(unsigned long segment)
  {
    components_.push_back(Component());
    components_.back().setSegment(segment);
  }

private:
  std::vector<Component> components_;
};

}

#endif

<|endoftext|>


<commit_before>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.

#include <librealsense2/rs.hpp> // Include RealSense Cross Platform API
#include "example.hpp"          // Include short list of convenience functions for rendering

// Capture Example demonstrates how to
// capture depth and color video streams and render them to the screen
int main(int argc, char * argv[]) try
{
    rs2::log_to_console(RS2_LOG_SEVERITY_ERROR);
    // Create a simple OpenGL window for rendering:
    window app(1280, 720, "RealSense Capture Example");

    // Declare depth colorizer for pretty visualization of depth data
    rs2::colorizer color_map;
	color_map.set_option(RS2_OPTION_HISTOGRAM_EQUALIZATION_ENABLED, 0);
	color_map.set_option(RS2_OPTION_MAX_DISTANCE, 2.0f);
	color_map.set_option(RS2_OPTION_MIN_DISTANCE, 0.3f);
	color_map.set_option(RS2_OPTION_COLOR_SCHEME, 1.0f);

	rs2::disparity_transform depth_to_disparity(true);

    // Declare rates printer for showing streaming rates of the enabled streams.
    rs2::rates_printer printer;

    // Declare RealSense pipeline, encapsulating the actual device and sensors
    rs2::pipeline pipe;

    // Start streaming with default recommended configuration
    // The default video configuration contains Depth and Color streams
    // If a device is capable to stream IMU data, both Gyro and Accelerometer are enabled by default
    pipe.start();

    while (app) // Application still alive?
    {
        rs2::frameset data = pipe.wait_for_frames().    // Wait for next set of frames from the camera
                             apply_filter(printer).     // Print each enabled stream frame rate
							 apply_filter(depth_to_disparity).
							apply_filter(color_map);   // Find and colorize the depth data

        // The show method, when applied on frameset, break it to frames and upload each frame into a gl textures
        // Each texture is displayed on different viewport according to it's stream unique id
        app.show(data);
    }

    return EXIT_SUCCESS;
}
catch (const rs2::error & e)
{
    std::cerr << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n    " << e.what() << std::endl;
    return EXIT_FAILURE;
}
catch (const std::exception& e)
{
    std::cerr << e.what() << std::endl;
    return EXIT_FAILURE;
}<commit_msg>-Rollback official rs-capture example to original.<commit_after>// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2017 Intel Corporation. All Rights Reserved.

#include <librealsense2/rs.hpp> // Include RealSense Cross Platform API
#include "example.hpp"          // Include short list of convenience functions for rendering

// Capture Example demonstrates how to
// capture depth and color video streams and render them to the screen
int main(int argc, char * argv[]) try
{
    rs2::log_to_console(RS2_LOG_SEVERITY_ERROR);
    // Create a simple OpenGL window for rendering:
    window app(1280, 720, "RealSense Capture Example");

    // Declare depth colorizer for pretty visualization of depth data
    rs2::colorizer color_map;
    // Declare rates printer for showing streaming rates of the enabled streams.
    rs2::rates_printer printer;

    // Declare RealSense pipeline, encapsulating the actual device and sensors
    rs2::pipeline pipe;

    // Start streaming with default recommended configuration
    // The default video configuration contains Depth and Color streams
    // If a device is capable to stream IMU data, both Gyro and Accelerometer are enabled by default
    pipe.start();

    while (app) // Application still alive?
    {
        rs2::frameset data = pipe.wait_for_frames().    // Wait for next set of frames from the camera
                             apply_filter(printer).     // Print each enabled stream frame rate
                             apply_filter(color_map);   // Find and colorize the depth data

        // The show method, when applied on frameset, break it to frames and upload each frame into a gl textures
        // Each texture is displayed on different viewport according to it's stream unique id
        app.show(data);
    }

    return EXIT_SUCCESS;
}
catch (const rs2::error & e)
{
    std::cerr << "RealSense error calling " << e.get_failed_function() << "(" << e.get_failed_args() << "):\n    " << e.what() << std::endl;
    return EXIT_FAILURE;
}
catch (const std::exception& e)
{
    std::cerr << e.what() << std::endl;
    return EXIT_FAILURE;
}<|endoftext|>