<commit_before>#include "tracker.h"
#include <tracking.h>
#include <pref.hpp>
#include <axis.h>
#include <ltlib.h>
#include <../ltr_srv_master.h>
#include <../ltr_srv_slave.h>
#include <cstdio>
#include "ltr_gui_prefs.h"
#include <iostream>
#include <unistd.h>
#include <QApplication>
#include <QMessageBox>

Tracker *Tracker::trr = NULL;
char *com_fname = NULL;

class MasterThread : public QThread{
  public:
    void run();
};

void MasterThread::run()
{
  ltr_int_master(false);
}

Tracker& Tracker::trackerInst()
{
  if(trr == NULL){
    trr = new Tracker();
  }
  return *trr;
}

static void ltr_int_new_slave(char *name)
{
  TRACKER.signalNewSlave(name);
}

static void ltr_int_state_changed(void *param)
{
  (void) param;
  TRACKER.signalStateChange(ltr_int_get_tracking_state());
}

static buffering buf(3);
static bool initBuffers = true;
static void ltr_int_new_frame(struct frame_type *frame, void *param)
{
  (void) param;
  static struct frame_type local_frame;
  local_frame.bloblist = frame->bloblist;
  local_frame.width = frame->width;
  local_frame.height = frame->height;
  local_frame.counter = frame->counter;

  if(initBuffers){
    buf.resizeBuffers(frame->width, frame->height);
    initBuffers = false;
  }

  if(frame->bitmap != NULL){
    buf.bufferWritten();
  }
  buffer *b;
  if(buf.writeBuffer(&b)){
    frame->bitmap = b->getBuffer();
  }else{
    frame->bitmap = NULL;
  }

  TRACKER.signalNewFrame(&local_frame);
  static pose_t current_pose;
  ltr_int_get_camera_update(&(current_pose.yaw), &(current_pose.pitch), &(current_pose.roll),
                            &(current_pose.tx), &(current_pose.ty), &(current_pose.tz),
                            &(current_pose.counter));
  TRACKER.signalNewPose(&current_pose);
}

buffering *Tracker::getBuffers()
{
  return &buf;
}

Tracker::Tracker() : axes(LTR_AXES_T_INITIALIZER), axes_valid(false), currentProfile("Default"), common_ff(0.0)
{
  if(!ltr_int_gui_lock(true)){
    QMessageBox::warning(NULL, "Linuxtrack", "Another linuxtrack gui is running already!",
                         QMessageBox::Ok);
  }
  master = new MasterThread();
  ltr_int_set_callback_hooks(ltr_int_new_frame, ltr_int_state_changed, ltr_int_new_slave);
  setProfile(QString("Default"));
  axes_valid = true;
}

Tracker::~Tracker()
{
  if(master->isRunning()){
    ltr_int_request_shutdown();
    master->wait();
  }
}

void Tracker::signalStateChange(ltr_state_type current_state)
{
  emit stateChanged(current_state);
}

void Tracker::signalNewFrame(struct frame_type *frame)
{
  emit newFrame(frame);
}

void Tracker::signalNewPose(pose_t *pose)
{
  static pose_t processed;
  static pose_t unfiltered;
  processed = *pose;
  ltr_int_postprocess_axes(axes, &processed, &unfiltered);
  //std::cout<<"TRACKER: "<<pose->pitch<<" "<<unfiltered.pitch<<" "<<processed.pitch<<std::endl;
  emit newPose(pose, &unfiltered, &processed);
}

void Tracker::signalNewSlave(const char *name)
{
  ltr_axes_t tmp_axes = LTR_AXES_T_INITIALIZER;
  ltr_int_init_axes(&tmp_axes, name);
  for(int i = PITCH; i <= TZ; ++i){
    ltr_int_change(name, i, AXIS_ENABLED, ltr_int_get_axis_bool_param(tmp_axes, (axis_t)i, AXIS_ENABLED)?1.0:0.0);
    for(int j = AXIS_DEADZONE; j <= AXIS_FILTER; ++j){
      ltr_int_change(name, i, j, ltr_int_get_axis_param(tmp_axes, (axis_t)i, (axis_param_t)j));
    }
  }
  ltr_int_change(NULL, MISC, MISC_LEGR, ltr_int_use_oldrot()?1.0:0.0);
  ltr_int_change(NULL, MISC, MISC_ALTER, ltr_int_use_alter()?1.0:0.0);
  ltr_int_change(NULL, MISC, MISC_ALIGN, ltr_int_do_tr_align()?1.0:0.0);
  ltr_int_close_axes(&tmp_axes);
}

void Tracker::setProfile(QString p)
{
  axes_valid = false;
  ltr_int_close_axes(&axes);
  //PREF.setCustomSection(p);
  currentProfile = p;
  PREF.getProfileSection(currentProfile, profileSection);
  //std::cout<<"Set profile "<<currentProfile.toStdString()<<" - "<<p.toStdString()<<std::endl;
  ltr_int_init_axes(&axes, currentProfile.toStdString().c_str());

  common_ff = 1.0;
  int i;
  for(i = PITCH; i <= TZ; ++i){
    ffs[i] = ltr_int_get_axis_param(axes, (axis_t)i, AXIS_FILTER);
    if(common_ff > ffs[i]){
      common_ff = ffs[i];
    }
  }
  for(i = PITCH; i <= TZ; ++i){
    ffs[i] -= common_ff;
  }
  axes_valid = true;
  emit initAxes();
}

void Tracker::fromDefault()
{
  ltr_int_axes_from_default(&axes);
  emit initAxes();
}

void Tracker::start(QString &section)
{
  (void) section;
  initBuffers = true;
  buf.init();
  master->start();
}

void Tracker::pause()
{
  ltr_int_suspend_cmd();
}

void Tracker::wakeup()
{
  ltr_int_wakeup_cmd();
}

void Tracker::recenter()
{
  ltr_int_recenter_cmd();
}

void Tracker::stop()
{
  ltr_int_request_shutdown();
}

bool Tracker::axisChange(axis_t axis, axis_param_t elem, bool enabled)
{
  ltr_int_set_axis_bool_param(axes, axis, elem, enabled);
  emit axisChanged(axis, elem);
  ltr_int_change(profileSection.toStdString().c_str(), axis, elem, enabled?1.0:0.0);
  return true;
}

bool Tracker::miscChange(axis_param_t elem, bool enabled)
{
  ltr_int_change(NULL, MISC, elem, enabled?1.0:0.0);
  return true;
}

static float limit_ff(float val)
{
  if(val < 0.0) return 0.0;
  if(val > 2.0) return 2.0;
  return val;
}

bool Tracker::axisChange(axis_t axis, axis_param_t elem, float val)
{
  if(elem == AXIS_FILTER){
    ffs[axis] = val;
    val = limit_ff(val + common_ff);
  }
  bool res = ltr_int_set_axis_param(axes, axis, elem, val);
  emit axisChanged(axis, elem);
  ltr_int_change(profileSection.toStdString().c_str(), axis, elem, val);
  return res;
}

bool Tracker::axisGetBool(axis_t axis, axis_param_t elem)
{
  return ltr_int_get_axis_bool_param(axes, axis, elem);
}

float Tracker::axisGet(axis_t axis, axis_param_t elem)
{
  if(elem == AXIS_FILTER){
    return ffs[axis];
  }else{
    return ltr_int_get_axis_param(axes, axis, elem);
  }
}

float Tracker::axisGetValue(axis_t axis, float val)
{
  return ltr_int_val_on_axis(axes, axis, val);
}

bool Tracker::axisIsSymetrical(axis_t axis)
{
  return ltr_int_is_symetrical(axes, axis);
}

bool Tracker::setCommonFilterFactor(float c_f)
{
  common_ff = c_f;
  bool res = true;
  float val;
  for(int i = PITCH; i <= TZ; ++i){
    val = limit_ff(ffs[i] + common_ff);
    res &= ltr_int_set_axis_param(axes, (axis_t)i, AXIS_FILTER, val);
    emit axisChanged(i, AXIS_FILTER);
    ltr_int_change(profileSection.toStdString().c_str(), i, AXIS_FILTER, val);
  }
  emit setCommonFF(c_f);
  return res;
}

float Tracker::getCommonFilterFactor()
{
  return common_ff;
}

<commit_msg>Fixed a race when ltr_gui is quit when the tracking is running.<commit_after>#include "tracker.h"
#include <tracking.h>
#include <pref.hpp>
#include <axis.h>
#include <ltlib.h>
#include <../ltr_srv_master.h>
#include <../ltr_srv_slave.h>
#include <cstdio>
#include "ltr_gui_prefs.h"
#include <iostream>
#include <unistd.h>
#include <QApplication>
#include <QMessageBox>

Tracker *Tracker::trr = NULL;
char *com_fname = NULL;

class MasterThread : public QThread{
  public:
    void run();
};

void MasterThread::run()
{
  ltr_int_master(false);
}

Tracker& Tracker::trackerInst()
{
  if(trr == NULL){
    trr = new Tracker();
  }
  return *trr;
}

static void ltr_int_new_slave(char *name)
{
  TRACKER.signalNewSlave(name);
}

static void ltr_int_state_changed(void *param)
{
  (void) param;
  TRACKER.signalStateChange(ltr_int_get_tracking_state());
}

static buffering buf(3);
static bool initBuffers = true;
static void ltr_int_new_frame(struct frame_type *frame, void *param)
{
  (void) param;
  static struct frame_type local_frame;
  local_frame.bloblist = frame->bloblist;
  local_frame.width = frame->width;
  local_frame.height = frame->height;
  local_frame.counter = frame->counter;

  if(initBuffers){
    buf.resizeBuffers(frame->width, frame->height);
    initBuffers = false;
  }

  if(frame->bitmap != NULL){
    buf.bufferWritten();
  }
  buffer *b;
  if(buf.writeBuffer(&b)){
    frame->bitmap = b->getBuffer();
  }else{
    frame->bitmap = NULL;
  }

  TRACKER.signalNewFrame(&local_frame);
  static pose_t current_pose;
  ltr_int_get_camera_update(&(current_pose.yaw), &(current_pose.pitch), &(current_pose.roll),
                            &(current_pose.tx), &(current_pose.ty), &(current_pose.tz),
                            &(current_pose.counter));
  TRACKER.signalNewPose(&current_pose);
}

buffering *Tracker::getBuffers()
{
  return &buf;
}

Tracker::Tracker() : axes(LTR_AXES_T_INITIALIZER), axes_valid(false), currentProfile("Default"), common_ff(0.0)
{
  if(!ltr_int_gui_lock(true)){
    QMessageBox::warning(NULL, "Linuxtrack", "Another linuxtrack gui is running already!",
                         QMessageBox::Ok);
  }
  master = new MasterThread();
  ltr_int_set_callback_hooks(ltr_int_new_frame, ltr_int_state_changed, ltr_int_new_slave);
  setProfile(QString("Default"));
  axes_valid = true;
}

Tracker::~Tracker()
{
  if(master->isRunning()){
    ltr_int_request_shutdown();
    master->wait();
  }
}

void Tracker::signalStateChange(ltr_state_type current_state)
{
  emit stateChanged(current_state);
}

void Tracker::signalNewFrame(struct frame_type *frame)
{
  emit newFrame(frame);
}

void Tracker::signalNewPose(pose_t *pose)
{
  static pose_t processed;
  static pose_t unfiltered;
  processed = *pose;
  ltr_int_postprocess_axes(axes, &processed, &unfiltered);
  //std::cout<<"TRACKER: "<<pose->pitch<<" "<<unfiltered.pitch<<" "<<processed.pitch<<std::endl;
  emit newPose(pose, &unfiltered, &processed);
}

void Tracker::signalNewSlave(const char *name)
{
  ltr_axes_t tmp_axes = LTR_AXES_T_INITIALIZER;
  ltr_int_init_axes(&tmp_axes, name);
  for(int i = PITCH; i <= TZ; ++i){
    ltr_int_change(name, i, AXIS_ENABLED, ltr_int_get_axis_bool_param(tmp_axes, (axis_t)i, AXIS_ENABLED)?1.0:0.0);
    for(int j = AXIS_DEADZONE; j <= AXIS_FILTER; ++j){
      ltr_int_change(name, i, j, ltr_int_get_axis_param(tmp_axes, (axis_t)i, (axis_param_t)j));
    }
  }
  ltr_int_change(NULL, MISC, MISC_LEGR, ltr_int_use_oldrot()?1.0:0.0);
  ltr_int_change(NULL, MISC, MISC_ALTER, ltr_int_use_alter()?1.0:0.0);
  ltr_int_change(NULL, MISC, MISC_ALIGN, ltr_int_do_tr_align()?1.0:0.0);
  ltr_int_close_axes(&tmp_axes);
}

void Tracker::setProfile(QString p)
{
  axes_valid = false;
  ltr_int_close_axes(&axes);
  //PREF.setCustomSection(p);
  currentProfile = p;
  PREF.getProfileSection(currentProfile, profileSection);
  //std::cout<<"Set profile "<<currentProfile.toStdString()<<" - "<<p.toStdString()<<std::endl;
  ltr_int_init_axes(&axes, currentProfile.toStdString().c_str());

  common_ff = 1.0;
  int i;
  for(i = PITCH; i <= TZ; ++i){
    ffs[i] = ltr_int_get_axis_param(axes, (axis_t)i, AXIS_FILTER);
    if(common_ff > ffs[i]){
      common_ff = ffs[i];
    }
  }
  for(i = PITCH; i <= TZ; ++i){
    ffs[i] -= common_ff;
  }
  axes_valid = true;
  emit initAxes();
}

void Tracker::fromDefault()
{
  ltr_int_axes_from_default(&axes);
  emit initAxes();
}

void Tracker::start(QString &section)
{
  (void) section;
  initBuffers = true;
  buf.init();
  master->start();
}

void Tracker::pause()
{
  ltr_int_suspend_cmd();
}

void Tracker::wakeup()
{
  ltr_int_wakeup_cmd();
}

void Tracker::recenter()
{
  ltr_int_recenter_cmd();
}

void Tracker::stop()
{
  ltr_int_request_shutdown();
  if(master->isRunning()){
    ltr_int_request_shutdown();
    master->wait();
  }
}

bool Tracker::axisChange(axis_t axis, axis_param_t elem, bool enabled)
{
  ltr_int_set_axis_bool_param(axes, axis, elem, enabled);
  emit axisChanged(axis, elem);
  ltr_int_change(profileSection.toStdString().c_str(), axis, elem, enabled?1.0:0.0);
  return true;
}

bool Tracker::miscChange(axis_param_t elem, bool enabled)
{
  ltr_int_change(NULL, MISC, elem, enabled?1.0:0.0);
  return true;
}

static float limit_ff(float val)
{
  if(val < 0.0) return 0.0;
  if(val > 2.0) return 2.0;
  return val;
}

bool Tracker::axisChange(axis_t axis, axis_param_t elem, float val)
{
  if(elem == AXIS_FILTER){
    ffs[axis] = val;
    val = limit_ff(val + common_ff);
  }
  bool res = ltr_int_set_axis_param(axes, axis, elem, val);
  emit axisChanged(axis, elem);
  ltr_int_change(profileSection.toStdString().c_str(), axis, elem, val);
  return res;
}

bool Tracker::axisGetBool(axis_t axis, axis_param_t elem)
{
  return ltr_int_get_axis_bool_param(axes, axis, elem);
}

float Tracker::axisGet(axis_t axis, axis_param_t elem)
{
  if(elem == AXIS_FILTER){
    return ffs[axis];
  }else{
    return ltr_int_get_axis_param(axes, axis, elem);
  }
}

float Tracker::axisGetValue(axis_t axis, float val)
{
  return ltr_int_val_on_axis(axes, axis, val);
}

bool Tracker::axisIsSymetrical(axis_t axis)
{
  return ltr_int_is_symetrical(axes, axis);
}

bool Tracker::setCommonFilterFactor(float c_f)
{
  common_ff = c_f;
  bool res = true;
  float val;
  for(int i = PITCH; i <= TZ; ++i){
    val = limit_ff(ffs[i] + common_ff);
    res &= ltr_int_set_axis_param(axes, (axis_t)i, AXIS_FILTER, val);
    emit axisChanged(i, AXIS_FILTER);
    ltr_int_change(profileSection.toStdString().c_str(), i, AXIS_FILTER, val);
  }
  emit setCommonFF(c_f);
  return res;
}

float Tracker::getCommonFilterFactor()
{
  return common_ff;
}

<|endoftext|>


<commit_before>#include <bts/network/node.hpp>
#include <bts/network/config.hpp>
#include <bts/client/client.hpp>
#include <bts/network/exceptions.hpp>
#include <fc/io/raw.hpp>

namespace bts { namespace network {

   node::node()
   :_desired_peer_count(8)
   {
   }

   node::~node()
   {
      try {
         _server.close();
         auto tmp_copy = _peers;
         for( auto peer : tmp_copy )
         {
            peer->_socket.close();
         }
         _accept_loop.cancel();
         _attempt_new_connections_task.cancel();
         _keep_alive_task.cancel();
         try { _accept_loop.wait(); } catch ( ... ){}
         try { _attempt_new_connections_task.wait(); } catch ( ... ) {}
         try { _keep_alive_task.wait(); } catch ( ... ) {}
      }
      catch ( const fc::exception& e )
      {
         wlog( "${e}", ("e",e.to_detail_string() ) );
      }
   }
   void node::set_client( client_ptr c )
   {
      _client = c;
      _attempt_new_connections_task = fc::schedule( [=](){ attempt_new_connection(); }, fc::time_point::now() + fc::seconds(1) );
   }

   void node::listen( const fc::ip::endpoint& ep )
   { try {
      _accept_loop = fc::async( [this](){ accept_loop(); } );
      _keep_alive_task = fc::schedule( [this](){ broadcast_keep_alive(); }, fc::time_point::now() + fc::seconds(2) );
       ulog( "delegate node listening on ${ep}", ("ep",ep) );
       try {
         _server.listen( ep );
       } catch ( const fc::exception& e )
       {
          ulog( "${e}", ("e",e.to_detail_string() ) );
       }
   } FC_CAPTURE_AND_RETHROW( (ep) ) }

   vector<peer_info> node::get_peers()const
   {
      vector<peer_info> results;

      for( auto peer : _peers )
      {
         results.push_back( peer->info );
      }

      return results;
   }

   void node::accept_loop()
   {
      while( !_accept_loop.canceled() )
      {
         auto new_connection = std::make_shared<peer_connection>();
         _server.accept( new_connection->_socket );
         on_connect( new_connection );
      }
   }

   void node::on_received_message( const shared_ptr<peer_connection>& con,
                                   const message& msg )
   {
      try {
         switch ( (message_type)msg.type )
         {
            case message_type::signin:
               on_signin_request( con, msg.as<signin_request>() );
               break;
            case goodbye:
               on_goodbye( con, msg.as<goodbye_message>() );
               break;
            case peer_request:
               break;
            case peer_response:
               break;
            case block:
               on_block_message( con, msg.as<block_message>() );
               break;
            case keep_alive:
               ulog( "keep alive ${peer}", ("peer",con->_socket.remote_endpoint()) );
               break;
            default:
               FC_ASSERT( !"unknown message type", "",("type",msg.type) );
         }
      }
      catch ( const fc::exception& e )
      {
         ulog( "exception processing message ${m}", ("m",e.to_detail_string() ) );
         con->send_message( goodbye_message(e) );
         con->_socket.close();
      }
   } // on_received_message

   void node::on_peer_request( const shared_ptr<peer_connection>& con,
                               const peer_request_message& request )
   {
      FC_ASSERT( con->is_logged_in(), "not logged in" );
   }

   void node::on_peer_response( const shared_ptr<peer_connection>& con,
                                const peer_request_message& request )
   {

   }

   void node::on_block_message( const shared_ptr<peer_connection>& con,
                                const block_message& msg )
   {
       ulog( "received block ${block_num}", ("block_num",msg.block.block_num) );
       // copy this..
       vector<peer_connection_ptr> broadcast_list( _peers.begin(), _peers.end() );
       for( auto peer : broadcast_list )
       {
          if( peer != con )
          {
              fc::async( [peer, msg](){ peer->send_message(msg); } );
          }
       }
       _client->get_chain()->push_block( msg.block );
   }

   void node::broadcast_keep_alive()
   {
       // copy this..
       vector<peer_connection_ptr> broadcast_list( _peers.begin(), _peers.end() );
       for( auto peer : broadcast_list )
       {
           fc::async( [peer]() { peer->send_message( keep_alive_message( fc::time_point::now() )  ); } );
       }
       _keep_alive_task = fc::schedule( [this](){ broadcast_keep_alive(); }, fc::time_point::now() + fc::seconds(2) );
   }

   void node::on_signin_request( const shared_ptr<peer_connection>& con,
                                 const signin_request& request )
   { try {
       fc::ecc::public_key  signin_key( request.signature,
                                        fc::sha256::hash( (char*)&con->_shared_secret,
                                                          sizeof(con->_shared_secret) ) );

      auto chain   = _client->get_chain();
      auto account = chain->get_account_record( signin_key );

      FC_ASSERT( account.valid() );

      auto active_delegate_ids = chain->get_active_delegates();
      auto location = std::find( active_delegate_ids.begin(), active_delegate_ids.end(), account->id );

      FC_ASSERT( location != active_delegate_ids.end(),
                 "You must be an active delgate to login" )

      con->info.delegate_ids.push_back( signin_key );

   } FC_CAPTURE_AND_RETHROW() }

   void node::on_goodbye( const shared_ptr<peer_connection>& con,
                          const goodbye_message& msg )
   {
      if( msg.reason )
      {
         elog( "Peer ${ep} disconnected us:\n${reason}",
               ("ep",con->_socket.remote_endpoint())("e",msg.reason->to_detail_string() ) );
      }
      con->_socket.close();
   }

   void node::connect_to( const fc::ip::endpoint& remote_peer )
   { try {
      ulog( "attempting to connect to ${peer}", ("peer",remote_peer) );
      _potential_peers[remote_peer].peer_endpoint = remote_peer;

      for( auto con : _peers )
      {
         if( con->_socket.remote_endpoint() == remote_peer )
            return; // already connected
      }

      auto con = std::make_shared<peer_connection>();
      ulog( "bind... to ${ep}", ("ep", _server.local_endpoint() ) );
      con->_socket.bind( _server.local_endpoint() );
      con->_socket.connect_to( remote_peer );
      on_connect( con );
   } FC_CAPTURE_AND_RETHROW( (remote_peer) ) }

   void node::on_connect( const shared_ptr<peer_connection>& con )
   { try {
      _peers.insert(con);
      auto remote_ep = con->_socket.remote_endpoint();
      ulog( "node connected ${e}", ("e", remote_ep ) );

      _potential_peers[remote_ep].peer_endpoint = remote_ep;
      _potential_peers[remote_ep].is_connected    = true;

      con->connection_closed.connect(
              [this]( const shared_ptr<peer_connection>& con,
                      const optional<fc::exception>& err )
              {
                 on_disconnect( con, err );
              } );
      con->received_message.connect(
              [this]( const shared_ptr<peer_connection>& con,
                      const message& msg )
              {
                 on_received_message( con, msg );
              } );
      con->start_read_loop();
   } FC_CAPTURE_AND_RETHROW() }

   void node::on_disconnect( const shared_ptr<peer_connection>& con,
                             const optional<fc::exception>& err )
   {
      auto remote_ep = con->_socket.remote_endpoint();
      ulog( "node disconnected ${e}", ("e", remote_ep ) );
      _potential_peers[remote_ep].peer_endpoint = remote_ep;
      _potential_peers[remote_ep].is_connected    = false;
      _potential_peers[remote_ep].failed_attempts++;

      if( err )
      {
          wlog( "disconnecting peer ${reason}", ("reason", err->to_detail_string() ) );
      }
      _peers.erase( con );
   }

   void node::signin( const vector<fc::ecc::private_key>& keys )
   { try {
      for( auto key : keys )
      {
         auto itr = std::find( _signin_keys.begin(), _signin_keys.end(), key );
         if( itr == _signin_keys.end() )
         {
            _signin_keys.push_back( key );

            auto peers_copy = _peers;
            // send sign message to all peers
            for( auto peer : peers_copy )
            {
               peer->signin( key );
            }
         }
      }
   } FC_CAPTURE_AND_RETHROW() }

   void node::attempt_new_connection()
   {
      for( auto p : _potential_peers )
      {
        // try a connection...
        if( !p.second.is_connected )
        {
           try {
              connect_to( p.second.peer_endpoint );
              p.second.last_connect_attempt = fc::time_point::now();
           }
           catch ( const fc::exception& e )
           {
              wlog( "${ep} : ${e}", ("ep", p.second.peer_endpoint )("e",e.to_detail_string() ) );
              p.second.last_connect_attempt = fc::time_point::now();
              p.second.failed_attempts++;
           }
        }
      }
      if( _peers.size() < _desired_peer_count )
      {
         ulog( "attempting new connections to peers: ${d} of ${desired}", ("d",_peers.size())("desired",_desired_peer_count) );
         _attempt_new_connections_task = fc::schedule( [=](){ attempt_new_connection(); }, fc::time_point::now() + fc::seconds(60) );
      }
      else {
         ulog( "we have the desired number of peers: ${d} of ${desired}", ("d",_peers.size())("desired",_desired_peer_count) );
      }
   }

   void node::broadcast_block( const full_block& block_to_broadcast )
   {
       ulog( "broadcasting block ${b}", ("b",block_to_broadcast.block_num) );
       vector<peer_connection_ptr> broadcast_list( _peers.begin(), _peers.end() );
       for( auto peer : broadcast_list )
       {
          fc::async( [peer, block_to_broadcast](){ peer->send_message(block_message(block_to_broadcast) ); } );
       }
   }

} } // bts::network
<commit_msg>more print<commit_after>#include <bts/network/node.hpp>
#include <bts/network/config.hpp>
#include <bts/client/client.hpp>
#include <bts/network/exceptions.hpp>
#include <fc/io/raw.hpp>

namespace bts { namespace network {

   node::node()
   :_desired_peer_count(8)
   {
   }

   node::~node()
   {
      try {
         _server.close();
         auto tmp_copy = _peers;
         for( auto peer : tmp_copy )
         {
            peer->_socket.close();
         }
         _accept_loop.cancel();
         _attempt_new_connections_task.cancel();
         _keep_alive_task.cancel();
         try { _accept_loop.wait(); } catch ( ... ){}
         try { _attempt_new_connections_task.wait(); } catch ( ... ) {}
         try { _keep_alive_task.wait(); } catch ( ... ) {}
      }
      catch ( const fc::exception& e )
      {
         wlog( "${e}", ("e",e.to_detail_string() ) );
      }
   }
   void node::set_client( client_ptr c )
   {
      _client = c;
      _attempt_new_connections_task = fc::schedule( [=](){ attempt_new_connection(); }, fc::time_point::now() + fc::seconds(1) );
   }

   void node::listen( const fc::ip::endpoint& ep )
   { try {
      _accept_loop = fc::async( [this](){ accept_loop(); } );
      _keep_alive_task = fc::schedule( [this](){ broadcast_keep_alive(); }, fc::time_point::now() + fc::seconds(2) );
       ulog( "delegate node listening on ${ep}", ("ep",ep) );
       try {
         _server.listen( ep );
       } catch ( const fc::exception& e )
       {
          ulog( "${e}", ("e",e.to_detail_string() ) );
       }
   } FC_CAPTURE_AND_RETHROW( (ep) ) }

   vector<peer_info> node::get_peers()const
   {
      vector<peer_info> results;

      for( auto peer : _peers )
      {
         results.push_back( peer->info );
      }

      return results;
   }

   void node::accept_loop()
   {
      while( !_accept_loop.canceled() )
      {
         auto new_connection = std::make_shared<peer_connection>();
         _server.accept( new_connection->_socket );
         on_connect( new_connection );
      }
   }

   void node::on_received_message( const shared_ptr<peer_connection>& con,
                                   const message& msg )
   {
      try {
         ulog( "type ${t}", ("t",msg.type) );
         switch ( (message_type)msg.type )
         {
            case message_type::signin:
               on_signin_request( con, msg.as<signin_request>() );
               break;
            case goodbye:
               on_goodbye( con, msg.as<goodbye_message>() );
               break;
            case peer_request:
               break;
            case peer_response:
               break;
            case block:
               ulog( "on block message" );
               on_block_message( con, msg.as<block_message>() );
               break;
            case keep_alive:
               ulog( "keep alive ${peer}", ("peer",con->_socket.remote_endpoint()) );
               break;
            default:
               FC_ASSERT( !"unknown message type", "",("type",msg.type) );
         }
      }
      catch ( const fc::exception& e )
      {
         ulog( "exception processing message ${m}", ("m",e.to_detail_string() ) );
         con->send_message( goodbye_message(e) );
         con->_socket.close();
      }
   } // on_received_message

   void node::on_peer_request( const shared_ptr<peer_connection>& con,
                               const peer_request_message& request )
   {
      FC_ASSERT( con->is_logged_in(), "not logged in" );
   }

   void node::on_peer_response( const shared_ptr<peer_connection>& con,
                                const peer_request_message& request )
   {

   }

   void node::on_block_message( const shared_ptr<peer_connection>& con,
                                const block_message& msg )
   {
       ulog( "received block ${block_num}", ("block_num",msg.block.block_num) );
       // copy this..
       vector<peer_connection_ptr> broadcast_list( _peers.begin(), _peers.end() );
       for( auto peer : broadcast_list )
       {
          if( peer != con )
          {
              fc::async( [peer, msg](){ peer->send_message(msg); } );
          }
       }
       _client->get_chain()->push_block( msg.block );
   }

   void node::broadcast_keep_alive()
   {
       // copy this..
       vector<peer_connection_ptr> broadcast_list( _peers.begin(), _peers.end() );
       for( auto peer : broadcast_list )
       {
           fc::async( [peer]() { peer->send_message( keep_alive_message( fc::time_point::now() )  ); } );
       }
       _keep_alive_task = fc::schedule( [this](){ broadcast_keep_alive(); }, fc::time_point::now() + fc::seconds(2) );
   }

   void node::on_signin_request( const shared_ptr<peer_connection>& con,
                                 const signin_request& request )
   { try {
       fc::ecc::public_key  signin_key( request.signature,
                                        fc::sha256::hash( (char*)&con->_shared_secret,
                                                          sizeof(con->_shared_secret) ) );

      auto chain   = _client->get_chain();
      auto account = chain->get_account_record( signin_key );

      FC_ASSERT( account.valid() );

      auto active_delegate_ids = chain->get_active_delegates();
      auto location = std::find( active_delegate_ids.begin(), active_delegate_ids.end(), account->id );

      FC_ASSERT( location != active_delegate_ids.end(),
                 "You must be an active delgate to login" )

      con->info.delegate_ids.push_back( signin_key );

   } FC_CAPTURE_AND_RETHROW() }

   void node::on_goodbye( const shared_ptr<peer_connection>& con,
                          const goodbye_message& msg )
   {
      if( msg.reason )
      {
         elog( "Peer ${ep} disconnected us:\n${reason}",
               ("ep",con->_socket.remote_endpoint())("e",msg.reason->to_detail_string() ) );
      }
      con->_socket.close();
   }

   void node::connect_to( const fc::ip::endpoint& remote_peer )
   { try {
      ulog( "attempting to connect to ${peer}", ("peer",remote_peer) );
      _potential_peers[remote_peer].peer_endpoint = remote_peer;

      for( auto con : _peers )
      {
         if( con->_socket.remote_endpoint() == remote_peer )
            return; // already connected
      }

      auto con = std::make_shared<peer_connection>();
      ulog( "bind... to ${ep}", ("ep", _server.local_endpoint() ) );
      con->_socket.bind( _server.local_endpoint() );
      con->_socket.connect_to( remote_peer );
      on_connect( con );
   } FC_CAPTURE_AND_RETHROW( (remote_peer) ) }

   void node::on_connect( const shared_ptr<peer_connection>& con )
   { try {
      _peers.insert(con);
      auto remote_ep = con->_socket.remote_endpoint();
      ulog( "node connected ${e}", ("e", remote_ep ) );

      _potential_peers[remote_ep].peer_endpoint = remote_ep;
      _potential_peers[remote_ep].is_connected    = true;

      con->connection_closed.connect(
              [this]( const shared_ptr<peer_connection>& con,
                      const optional<fc::exception>& err )
              {
                 on_disconnect( con, err );
              } );
      con->received_message.connect(
              [this]( const shared_ptr<peer_connection>& con,
                      const message& msg )
              {
                 on_received_message( con, msg );
              } );
      con->start_read_loop();
   } FC_CAPTURE_AND_RETHROW() }

   void node::on_disconnect( const shared_ptr<peer_connection>& con,
                             const optional<fc::exception>& err )
   {
      auto remote_ep = con->_socket.remote_endpoint();
      ulog( "node disconnected ${e}", ("e", remote_ep ) );
      _potential_peers[remote_ep].peer_endpoint = remote_ep;
      _potential_peers[remote_ep].is_connected    = false;
      _potential_peers[remote_ep].failed_attempts++;

      if( err )
      {
          wlog( "disconnecting peer ${reason}", ("reason", err->to_detail_string() ) );
      }
      _peers.erase( con );
   }

   void node::signin( const vector<fc::ecc::private_key>& keys )
   { try {
      for( auto key : keys )
      {
         auto itr = std::find( _signin_keys.begin(), _signin_keys.end(), key );
         if( itr == _signin_keys.end() )
         {
            _signin_keys.push_back( key );

            auto peers_copy = _peers;
            // send sign message to all peers
            for( auto peer : peers_copy )
            {
               peer->signin( key );
            }
         }
      }
   } FC_CAPTURE_AND_RETHROW() }

   void node::attempt_new_connection()
   {
      for( auto p : _potential_peers )
      {
        // try a connection...
        if( !p.second.is_connected )
        {
           try {
              connect_to( p.second.peer_endpoint );
              p.second.last_connect_attempt = fc::time_point::now();
           }
           catch ( const fc::exception& e )
           {
              wlog( "${ep} : ${e}", ("ep", p.second.peer_endpoint )("e",e.to_detail_string() ) );
              p.second.last_connect_attempt = fc::time_point::now();
              p.second.failed_attempts++;
           }
        }
      }
      if( _peers.size() < _desired_peer_count )
      {
         ulog( "attempting new connections to peers: ${d} of ${desired}", ("d",_peers.size())("desired",_desired_peer_count) );
         _attempt_new_connections_task = fc::schedule( [=](){ attempt_new_connection(); }, fc::time_point::now() + fc::seconds(60) );
      }
      else {
         ulog( "we have the desired number of peers: ${d} of ${desired}", ("d",_peers.size())("desired",_desired_peer_count) );
      }
   }

   void node::broadcast_block( const full_block& block_to_broadcast )
   {
       ulog( "broadcasting block ${b}", ("b",block_to_broadcast.block_num) );
       vector<peer_connection_ptr> broadcast_list( _peers.begin(), _peers.end() );
       for( auto peer : broadcast_list )
       {
          fc::async( [peer, block_to_broadcast](){ peer->send_message(block_message(block_to_broadcast) ); } );
       }
   }

} } // bts::network
<|endoftext|>


<commit_before><commit_msg>V4l2Device: Fix resource leak and add error checking<commit_after><|endoftext|>


<commit_before>/*****************************************************************************
 * stream_io_callback.cpp : matroska demuxer
 *****************************************************************************
 * Copyright (C) 2003-2004, 2010 VLC authors and VideoLAN
 * $Id$
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *          Steve Lhomme <steve.lhomme@free.fr>
 *
 * 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 "stream_io_callback.hpp"

#include "matroska_segment.hpp"
#include "demux.hpp"

/*****************************************************************************
 * Stream managment
 *****************************************************************************/
vlc_stream_io_callback::vlc_stream_io_callback( stream_t *s_, bool b_owner_ )
                       : s( s_), b_owner( b_owner_ )
{
    mb_eof = false;
}

uint32 vlc_stream_io_callback::read( void *p_buffer, size_t i_size )
{
    if( i_size <= 0 || mb_eof )
        return 0;

    return stream_Read( s, p_buffer, i_size );
}

void vlc_stream_io_callback::setFilePointer(int64_t i_offset, seek_mode mode )
{
    int64_t i_pos, i_size;
    int64_t i_current = stream_Tell( s );

    switch( mode )
    {
        case seek_beginning:
            i_pos = i_offset;
            break;
        case seek_end:
            i_pos = stream_Size( s ) - i_offset;
            break;
        default:
            i_pos= i_current + i_offset;
            break;
    }

    if(i_pos == i_current)
        return;

    if( i_pos < 0 || ( ( i_size = stream_Size( s ) ) != 0 && i_pos >= i_size ) )
    {
        mb_eof = true;
        return;
    }

    mb_eof = false;
    if( stream_Seek( s, i_pos ) )
    {
        mb_eof = true;
    }
    return;
}

uint64 vlc_stream_io_callback::getFilePointer( void )
{
    if ( s == NULL )
        return 0;
    return stream_Tell( s );
}

size_t vlc_stream_io_callback::write(const void *, size_t )
{
    return 0;
}

uint64 vlc_stream_io_callback::toRead( void )
{
    uint64_t i_size;

    if( s == NULL)
        return 0;

    i_size = stream_Size( s );

    if( i_size == 0 )
        return UINT64_MAX;

    return (uint64) i_size - stream_Tell( s );
}

<commit_msg>mkv: fix return values of ebml callbacks<commit_after>/*****************************************************************************
 * stream_io_callback.cpp : matroska demuxer
 *****************************************************************************
 * Copyright (C) 2003-2004, 2010 VLC authors and VideoLAN
 * $Id$
 *
 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
 *          Steve Lhomme <steve.lhomme@free.fr>
 *
 * 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 "stream_io_callback.hpp"

#include "matroska_segment.hpp"
#include "demux.hpp"

/*****************************************************************************
 * Stream managment
 *****************************************************************************/
vlc_stream_io_callback::vlc_stream_io_callback( stream_t *s_, bool b_owner_ )
                       : s( s_), b_owner( b_owner_ )
{
    mb_eof = false;
}

uint32 vlc_stream_io_callback::read( void *p_buffer, size_t i_size )
{
    if( i_size <= 0 || mb_eof )
        return 0;

    int i_ret = stream_Read( s, p_buffer, i_size );
    return i_ret < 0 ? 0 : i_ret;
}

void vlc_stream_io_callback::setFilePointer(int64_t i_offset, seek_mode mode )
{
    int64_t i_pos, i_size;
    int64_t i_current = stream_Tell( s );

    switch( mode )
    {
        case seek_beginning:
            i_pos = i_offset;
            break;
        case seek_end:
            i_pos = stream_Size( s ) - i_offset;
            break;
        default:
            i_pos= i_current + i_offset;
            break;
    }

    if(i_pos == i_current)
        return;

    if( i_pos < 0 || ( ( i_size = stream_Size( s ) ) != 0 && i_pos >= i_size ) )
    {
        mb_eof = true;
        return;
    }

    mb_eof = false;
    if( stream_Seek( s, i_pos ) )
    {
        mb_eof = true;
    }
    return;
}

uint64 vlc_stream_io_callback::getFilePointer( void )
{
    if ( s == NULL )
        return 0;
    return stream_Tell( s );
}

size_t vlc_stream_io_callback::write(const void *, size_t )
{
    return 0;
}

uint64 vlc_stream_io_callback::toRead( void )
{
    uint64_t i_size;

    if( s == NULL)
        return 0;

    i_size = stream_Size( s );

    if( i_size <= 0 )
        return UINT64_MAX;

    return (uint64) i_size - stream_Tell( s );
}

<|endoftext|>


<commit_before><commit_msg>Change uses of (long long int) and (std::string) into asInt() and asString() where appropiate.<commit_after><|endoftext|>


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

#ifndef UTIL_RINGBUFFER_HPP
#define UTIL_RINGBUFFER_HPP

#include <cstring>
#include <cassert>
#include <cstdio>

/**
 *  See:
 *  HeapRingBuffer
 *  MemoryRingBuffer
**/

class RingBuffer {
public:
  int write(const void* buffer, int length) noexcept
  {
    const char* data = (const char*) buffer;
    if (length > free_space()) {
      length = free_space();
      if (length == 0) return 0;
    }

    // check if we are going around the buffer ...
    int wrap = (end + length) - this->cap;

    if (wrap > 0) {
      memcpy(at_end() ,    data, length - wrap);
      memcpy(this->buffer, data + length - wrap, wrap);
    }
    else {
      memcpy(at_end(), data, length);
    }
    this->used += length;
    // make sure it wraps properly around
    this->end = (this->end + length) % capacity();
    return length;
  }

  int read(char* dest, int length) noexcept
  {
    if (length > used_space()) {
      length = used_space();
      if (length == 0) return 0;
    }

    // check if we are going around the buffer ...
    int wrap = (start + length) - this->cap;

    if (wrap > 0) {
      memcpy(dest,                 at_start(),   length - wrap);
      memcpy(dest + length - wrap, this->buffer, wrap);
    } else {
      memcpy(dest, at_start(), length);
    }
    this->used -= length;
    // make sure it wraps properly around
    this->start = (this->start + length) % capacity();
    return length;
  }

  int discard(int length) noexcept
  {
    // do nothing if not enough used space to discard anyway
    if (length > used_space()) return 0;
    // commit no-op write and return length
    this->used -= length;
    this->start = (this->start + length) % capacity();
    return length;
  }

  int capacity() const noexcept {
    return this->cap;
  }
  int size() const noexcept {
    return used_space();
  }

  int used_space() const noexcept {
    return this->used;
  }
  int free_space() const noexcept {
    return capacity() - used_space();
  }

  bool full() const noexcept {
    return used_space() == capacity();
  }
  bool empty() const noexcept {
    return used_space() == 0;
  }

  bool is_valid() const noexcept {
    return (used <= cap and cap > 0)
      and (start < cap and start >= 0)
      and (end < cap and end >= 0);
  }

  // rotate buffer until it becomes sequential
  const char* sequentialize()
  {
    // not optimized, but if we assume the buffer is always full,
    // then there is no point in doing anything here
    int count = 0;
    int offset = 0;

    while (count < size())
    {
      int index = offset;
      const char tmp  = buffer[index];
      int index2 = (start + index) % capacity();

      while (index2 != offset)
      {
        buffer[index] = buffer[index2];
        count++;

        index = index2;
        index2 = (start + index) % capacity();
      }

      buffer[index] = tmp;
      count++;

      offset++;
    }
    // update internals
    this->start = 0;
    this->end = size();
    return this->buffer;
  }

  const char* data() const noexcept {
    return this->buffer;
  }

protected:
  RingBuffer(char* rbuffer, int size)
    : cap(size), buffer(rbuffer)
  {
    assert(size > 0);
  }

  const char* at_start() const noexcept {
    return &this->buffer[this->start];
  }
  char* at_end() const noexcept {
    return &this->buffer[this->end];
  }

  const int  cap;
  int  start = 0;
  int  end   = 0;
  int  used  = 0;
  char* buffer;
};

class HeapRingBuffer : public RingBuffer {
public:
  HeapRingBuffer(int size)
    : RingBuffer(new char[size], size) {}
  ~HeapRingBuffer() {
    delete[] this->buffer;
  }
};

class MemoryRingBuffer : public RingBuffer {
public:
  MemoryRingBuffer(char* location, int size)
    : RingBuffer(location, size) {}

  MemoryRingBuffer(char* loc, const int cap,
                   int start, int end, int used)
    : RingBuffer(loc, cap)
  {
    this->start = start;
    this->end   = end;
    this->used  = used;
  }

  ~MemoryRingBuffer() {}
};

template <int N>
class FixedRingBuffer : public RingBuffer {
public:
  FixedRingBuffer()
    : RingBuffer(m_buffer, N) {}
  ~FixedRingBuffer() {}

private:
  char m_buffer[N];
};

#endif
<commit_msg>util: MemoryRingBuffer now accepts void*<commit_after>// This file is a part of the IncludeOS unikernel - www.includeos.org
//
// Copyright 2015 Oslo and Akershus University College of Applied Sciences
// and Alfred Bratterud
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef UTIL_RINGBUFFER_HPP
#define UTIL_RINGBUFFER_HPP

#include <cstring>
#include <cassert>
#include <cstdio>

/**
 *  See:
 *  HeapRingBuffer
 *  MemoryRingBuffer
**/

class RingBuffer {
public:
  int write(const void* buffer, int length) noexcept
  {
    const char* data = (const char*) buffer;
    if (length > free_space()) {
      length = free_space();
      if (length == 0) return 0;
    }

    // check if we are going around the buffer ...
    int wrap = (end + length) - this->cap;

    if (wrap > 0) {
      memcpy(at_end() ,    data, length - wrap);
      memcpy(this->buffer, data + length - wrap, wrap);
    }
    else {
      memcpy(at_end(), data, length);
    }
    this->used += length;
    // make sure it wraps properly around
    this->end = (this->end + length) % capacity();
    return length;
  }

  int read(char* dest, int length) noexcept
  {
    if (length > used_space()) {
      length = used_space();
      if (length == 0) return 0;
    }

    // check if we are going around the buffer ...
    int wrap = (start + length) - this->cap;

    if (wrap > 0) {
      memcpy(dest,                 at_start(),   length - wrap);
      memcpy(dest + length - wrap, this->buffer, wrap);
    } else {
      memcpy(dest, at_start(), length);
    }
    this->used -= length;
    // make sure it wraps properly around
    this->start = (this->start + length) % capacity();
    return length;
  }

  int discard(int length) noexcept
  {
    // do nothing if not enough used space to discard anyway
    if (length > used_space()) return 0;
    // commit no-op write and return length
    this->used -= length;
    this->start = (this->start + length) % capacity();
    return length;
  }

  int capacity() const noexcept {
    return this->cap;
  }
  int size() const noexcept {
    return used_space();
  }

  int used_space() const noexcept {
    return this->used;
  }
  int free_space() const noexcept {
    return capacity() - used_space();
  }

  bool full() const noexcept {
    return used_space() == capacity();
  }
  bool empty() const noexcept {
    return used_space() == 0;
  }

  bool is_valid() const noexcept {
    return (used <= cap and cap > 0)
      and (start < cap and start >= 0)
      and (end < cap and end >= 0);
  }

  // rotate buffer until it becomes sequential
  const char* sequentialize()
  {
    // not optimized, but if we assume the buffer is always full,
    // then there is no point in doing anything here
    int count = 0;
    int offset = 0;

    while (count < size())
    {
      int index = offset;
      const char tmp  = buffer[index];
      int index2 = (start + index) % capacity();

      while (index2 != offset)
      {
        buffer[index] = buffer[index2];
        count++;

        index = index2;
        index2 = (start + index) % capacity();
      }

      buffer[index] = tmp;
      count++;

      offset++;
    }
    // update internals
    this->start = 0;
    this->end = size();
    return this->buffer;
  }

  const char* data() const noexcept {
    return this->buffer;
  }

protected:
  RingBuffer(void* rbuffer, int size)
    : cap(size), buffer((char*) rbuffer)
  {
    assert(size > 0);
  }

  const char* at_start() const noexcept {
    return &this->buffer[this->start];
  }
  char* at_end() const noexcept {
    return &this->buffer[this->end];
  }

  const int  cap;
  int  start = 0;
  int  end   = 0;
  int  used  = 0;
  char* buffer;
};

class HeapRingBuffer : public RingBuffer {
public:
  HeapRingBuffer(int size)
    : RingBuffer(new char[size], size) {}
  ~HeapRingBuffer() {
    delete[] this->buffer;
  }
};

class MemoryRingBuffer : public RingBuffer {
public:
  MemoryRingBuffer(void* location, int size)
    : RingBuffer(location, size) {}

  MemoryRingBuffer(void* loc, const int cap,
                   int start, int end, int used)
    : RingBuffer(loc, cap)
  {
    this->start = start;
    this->end   = end;
    this->used  = used;
  }

  ~MemoryRingBuffer() {}
};

template <int N>
class FixedRingBuffer : public RingBuffer {
public:
  FixedRingBuffer()
    : RingBuffer(m_buffer, N) {}
  ~FixedRingBuffer() {}

private:
  char m_buffer[N];
};

#endif
<|endoftext|>


<commit_before>#include "erlv8.hh"

TickHandler(SetTickHandler) {
  ErlNifEnv *ref_env = enif_alloc_env();
  ERL_NIF_TERM set_ref = enif_make_copy(ref_env, tick_ref);
  ERL_NIF_TERM value = enif_make_copy(ref_env, array[3]); // stashing it away since Set() might call an accessor, which might change vm->env
  val_res_t *obj_res;
  if (enif_get_resource(vm->env,array[1],val_resource,(void **)(&obj_res))) {
	LHCS(obj_res->ctx);

	v8::PropertyAttribute property_attribute = v8::None;

	if (arity == 5) {
	  property_attribute = term_to_property_attribute(vm->env,array[4]);
	}

	obj_res->val->ToObject()->Set(term_to_js(vm->env,array[2]),term_to_js(ref_env,value), property_attribute);

	SEND(vm->server,
		 enif_make_tuple3(env,
						  enif_make_atom(env,"result"),
						  enif_make_copy(env,set_ref),
						  enif_make_copy(env,value)));
  }
  enif_free_env(ref_env);
  return DONE;
}

TickHandler(SetProtoTickHandler) {
  ErlNifEnv *ref_env = enif_alloc_env();
  ERL_NIF_TERM set_ref = enif_make_copy(ref_env, tick_ref);
  val_res_t *obj_res;
  if (enif_get_resource(vm->env,array[1],val_resource,(void **)(&obj_res))) {
	LHCS(obj_res->ctx);

	ERL_NIF_TERM result =  enif_make_atom(ref_env, obj_res->val->ToObject()->SetPrototype(term_to_js(ref_env,array[2])) ? "true" : "false");

	SEND(vm->server,
		 enif_make_tuple3(env,
						  enif_make_atom(env,"result"),
						  enif_make_copy(env,set_ref),
						  result));
  }
  enif_free_env(ref_env);
  return DONE;
}

TickHandler(SetHiddenTickHandler) {
  ErlNifEnv *ref_env = enif_alloc_env();
  ERL_NIF_TERM set_ref = enif_make_copy(ref_env, tick_ref);
  val_res_t *obj_res;
  if (enif_get_resource(vm->env,array[1],val_resource,(void **)(&obj_res))) {
	LHCS(obj_res->ctx);

	obj_res->val->ToObject()->SetHiddenValue(term_to_js(ref_env,array[2])->ToString(),term_to_js(ref_env,array[3]));

	SEND(vm->server,
		 enif_make_tuple3(env,
						  enif_make_atom(env,"result"),
						  enif_make_copy(env,set_ref),
						  enif_make_copy(env,array[2])));
  }
  enif_free_env(ref_env);
  return DONE;
}

TickHandler(SetInternalTickHandler) {
  ErlNifEnv *ref_env = enif_alloc_env();
  ERL_NIF_TERM set_ref = enif_make_copy(ref_env, tick_ref);
  val_res_t *obj_res;
  char name[MAX_ATOM_LEN];
  unsigned len;

  if (enif_get_resource(vm->env,array[1],val_resource,(void **)(&obj_res))) {
	LHCS(obj_res->ctx);

	int index;
	enif_get_int(vm->env, array[2], &index);

	if (index < 0 || (index + 1 > obj_res->val->ToObject()->InternalFieldCount())) {
	  		SEND(vm->server,
			 enif_make_tuple3(env,
							  enif_make_atom(env,"result"),
							  enif_make_copy(env,set_ref),
							  enif_make_atom(env,"error")));
	} else {

	  if (!strcmp(tick_name,"set_internal_extern")) {
		enif_get_atom_length(vm->env, array[4], &len, ERL_NIF_LATIN1);
		enif_get_atom(vm->env,array[4],(char *)&name,len + 1, ERL_NIF_LATIN1);
		v8::Handle<v8::Object> proto = extern_name_to_proto(vm, name);
		obj_res->val->ToObject()->SetInternalField(index,term_to_external(array[3]));
	  } else {
		obj_res->val->ToObject()->SetInternalField(index,term_to_js(vm->env,array[3]));
	  }

	  SEND(vm->server,
		   enif_make_tuple3(env,
							enif_make_atom(env,"result"),
							enif_make_copy(env,set_ref),
						  enif_make_copy(env,array[3])));
	}

  }
  enif_free_env(ref_env);
  return DONE;
}

v8::Handle<v8::Value> GetterFun(v8::Local<v8::String> property,const v8::AccessorInfo &info); // fwd
void SetterFun(v8::Local<v8::String> property,v8::Local<v8::Value> value,const v8::AccessorInfo &info); // fwd

void weak_accessor_data_cleaner(v8::Persistent<v8::Value> object, void * data) {
  if (object.IsNearDeath()) {
	object->ToObject()->DeleteHiddenValue(v8::String::New("_getter"));
	object->ToObject()->DeleteHiddenValue(v8::String::New("_setter"));
        object.Dispose();
        object.Clear();
  }
}

TickHandler(SetAccessorTickHandler) {
  char aname[MAX_ATOM_LEN];
  ErlNifEnv *ref_env = enif_alloc_env();
  ERL_NIF_TERM set_ref = enif_make_copy(ref_env, tick_ref);
  const char *atom_val;
  val_res_t *obj_res;
  if (enif_get_resource(vm->env,array[1],val_resource,(void **)(&obj_res))) {
	LHCS(obj_res->ctx);

	if (arity > 3) {
	  v8::Handle<v8::Value> name = term_to_js(vm->env,array[2]);
	  if (!name->IsString()) {
          goto badarg;
      }
	  v8::AccessorGetter getter = GetterFun;
	  v8::AccessorSetter setter = 0;
	  v8::Persistent<v8::Object> data = v8::Persistent<v8::Object>::New(v8::Object::New());
	  data.MakeWeak(NULL,weak_accessor_data_cleaner); // so that we'll release externals when we're done

	  if (term_to_js(vm->env,array[3])->IsUndefined()) {
          goto badarg;
	  } else {
		data->SetHiddenValue(v8::String::New("_getter"), term_to_external(array[3]));
	  }

	  if (arity > 4) {
		setter = SetterFun;
		data->SetHiddenValue(v8::String::New("_setter"), term_to_external(array[4]));
	  }

	  v8::AccessControl access_control = v8::DEFAULT;

	  if (arity > 5 && enif_is_atom(vm->env, array[5])) {
		unsigned len;
		enif_get_atom_length(vm->env, array[5], &len, ERL_NIF_LATIN1);
		enif_get_atom(vm->env,array[5], (char *) &aname,len + 1, ERL_NIF_LATIN1);
		if (!strcmp(aname,"default")) {
		  access_control = v8::DEFAULT;
		} else if (!strcmp(aname,"all_can_read")) {
		  access_control = v8::ALL_CAN_READ;
		} else if (!strcmp(aname,"all_can_write")) {
		  access_control = v8::ALL_CAN_WRITE;
		} else if (!strcmp(aname,"prohibits_overwriting")) {
		  access_control = v8::PROHIBITS_OVERWRITING;
		}
	  }

	  v8::PropertyAttribute property_attribute = v8::None;

	  if (arity > 6) {
		property_attribute = term_to_property_attribute(vm->env,array[6]);
	  }

      atom_val = obj_res->val->ToObject()->SetAccessor(name->ToString(), getter, setter, data,
																   access_control, property_attribute) ? "true" : "false";
      goto send;
	}
badarg:
    atom_val = "badarg";
send:
	SEND(vm->server,
		 enif_make_tuple3(env,
						  enif_make_atom(env,"result"),
						  enif_make_copy(env,set_ref),
						  enif_make_atom(env, atom_val)));
  }
  enif_free_env(ref_env);
  return DONE;
}

v8::Handle<v8::Value> GetterFun(v8::Local<v8::String> property,const v8::AccessorInfo &info) {
  v8::HandleScope handle_scope;
  VM * vm = (VM *)__ERLV8__(v8::Context::GetCurrent()->Global());

  v8::Local<v8::Object> data = info.Data()->ToObject();

  // each call gets a unique ref
  ERL_NIF_TERM ref = enif_make_ref(vm->env);

  // prepare arguments
  ERL_NIF_TERM *arr = (ERL_NIF_TERM *) malloc(sizeof(ERL_NIF_TERM) * 1);
  arr[0] = js_to_term(vm->env, property);
  ERL_NIF_TERM arglist = enif_make_list_from_array(vm->env,arr,1);
  free(arr);

  // send invocation request
  SEND(vm->server,
	   enif_make_tuple3(env,
						enif_make_copy(env,external_to_term(data->GetHiddenValue(v8::String::New("_getter")))),
						enif_make_tuple7(env,
										 enif_make_atom(env,"erlv8_fun_invocation"),
										 enif_make_atom(env,"false"),
										 js_to_term(env, info.Holder()),
										 js_to_term(env, info.This()),
										 enif_make_copy(env, ref),
										 enif_make_pid(env, vm->server),
										 enif_make_copy(env, external_to_term(v8::Context::GetCurrent()->Global()->GetHiddenValue(v8::String::New("__erlv8__ctx__"))))
										 ),
						enif_make_copy(env,arglist)));
  return vm->ticker(ref);
}

void SetterFun(v8::Local<v8::String> property,v8::Local<v8::Value> value,const v8::AccessorInfo &info) {
  v8::HandleScope handle_scope;
  VM * vm = (VM *)__ERLV8__(v8::Context::GetCurrent()->Global());

  v8::Local<v8::Object> data = info.Data()->ToObject();

  // each call gets a unique ref
  ERL_NIF_TERM ref = enif_make_ref(vm->env);

  // prepare arguments
  ERL_NIF_TERM *arr = (ERL_NIF_TERM *) malloc(sizeof(ERL_NIF_TERM) * 2);
  arr[0] = js_to_term(vm->env, property);
  arr[1] = js_to_term(vm->env, value);
  ERL_NIF_TERM arglist = enif_make_list_from_array(vm->env,arr,2);
  free(arr);

  // send invocation request
  SEND(vm->server,
	   enif_make_tuple3(env,
						enif_make_copy(env,external_to_term(data->GetHiddenValue(v8::String::New("_setter")))),
						enif_make_tuple7(env,
										 enif_make_atom(env,"erlv8_fun_invocation"),
										 enif_make_atom(env,"false"),
										 js_to_term(env, info.Holder()),
										 js_to_term(env, info.This()),
										 enif_make_copy(env, ref),
										 enif_make_pid(env, vm->server),
										 enif_make_copy(env, external_to_term(v8::Context::GetCurrent()->Global()->GetHiddenValue(v8::String::New("__erlv8__ctx__"))))
										 ),
						enif_make_copy(env,arglist)));
  vm->ticker(ref);
}
<commit_msg>Cleanup env usage in erlv8_set.cc<commit_after>#include "erlv8.hh"

TickHandler(SetTickHandler) {
  ErlNifEnv *tmp_env = enif_alloc_env();
  ERL_NIF_TERM value = enif_make_copy(tmp_env, array[3]); // stashing it away since Set() might call an accessor, which might change vm->env
  val_res_t *obj_res;
  if (enif_get_resource(vm->env,array[1],val_resource,(void **)(&obj_res))) {
	LHCS(obj_res->ctx);

	v8::PropertyAttribute property_attribute = v8::None;

	if (arity == 5) {
	  property_attribute = term_to_property_attribute(vm->env,array[4]);
	}

	obj_res->val->ToObject()->Set(term_to_js(vm->env,array[2]),term_to_js(vm->env,value), property_attribute);

	SEND(vm->server,
		 enif_make_tuple3(env,
						  enif_make_atom(env,"result"),
						  enif_make_copy(env,tick_ref),
						  enif_make_copy(env,value)));
  }
  enif_free_env(tmp_env);
  return DONE;
}

TickHandler(SetProtoTickHandler) {
  val_res_t *obj_res;
  if (enif_get_resource(vm->env,array[1],val_resource,(void **)(&obj_res))) {
	LHCS(obj_res->ctx);

    const char *atom_val = obj_res->val->ToObject()->SetPrototype(term_to_js(vm->env,array[2])) ? "true" : "false";

	SEND(vm->server,
		 enif_make_tuple3(env,
						  enif_make_atom(env,"result"),
						  enif_make_copy(env,tick_ref),
						  enif_make_atom(env,atom_val)));
  }
  return DONE;
}

TickHandler(SetHiddenTickHandler) {
  val_res_t *obj_res;
  if (enif_get_resource(vm->env,array[1],val_resource,(void **)(&obj_res))) {
	LHCS(obj_res->ctx);

	obj_res->val->ToObject()->SetHiddenValue(term_to_js(vm->env,array[2])->ToString(),term_to_js(vm->env,array[3]));

	SEND(vm->server,
		 enif_make_tuple3(env,
						  enif_make_atom(env,"result"),
						  enif_make_copy(env,tick_ref),
						  enif_make_copy(env,array[2])));
  }
  return DONE;
}

TickHandler(SetInternalTickHandler) {
  val_res_t *obj_res;
  char name[MAX_ATOM_LEN];
  unsigned len;

  if (enif_get_resource(vm->env,array[1],val_resource,(void **)(&obj_res))) {
	LHCS(obj_res->ctx);

	int index;
	enif_get_int(vm->env, array[2], &index);

	if (index < 0 || (index + 1 > obj_res->val->ToObject()->InternalFieldCount())) {
	  		SEND(vm->server,
			 enif_make_tuple3(env,
							  enif_make_atom(env,"result"),
							  enif_make_copy(env,tick_ref),
							  enif_make_atom(env,"error")));
	} else {

	  if (!strcmp(tick_name,"set_internal_extern")) {
		enif_get_atom_length(vm->env, array[4], &len, ERL_NIF_LATIN1);
		enif_get_atom(vm->env,array[4],(char *)&name,len + 1, ERL_NIF_LATIN1);
		v8::Handle<v8::Object> proto = extern_name_to_proto(vm, name);
		obj_res->val->ToObject()->SetInternalField(index,term_to_external(array[3]));
	  } else {
		obj_res->val->ToObject()->SetInternalField(index,term_to_js(vm->env,array[3]));
	  }

	  SEND(vm->server,
		   enif_make_tuple3(env,
							enif_make_atom(env,"result"),
							enif_make_copy(env,tick_ref),
						  enif_make_copy(env,array[3])));
	}
  }
  return DONE;
}

v8::Handle<v8::Value> GetterFun(v8::Local<v8::String> property,const v8::AccessorInfo &info); // fwd
void SetterFun(v8::Local<v8::String> property,v8::Local<v8::Value> value,const v8::AccessorInfo &info); // fwd

void weak_accessor_data_cleaner(v8::Persistent<v8::Value> object, void * data) {
  if (object.IsNearDeath()) {
	object->ToObject()->DeleteHiddenValue(v8::String::New("_getter"));
	object->ToObject()->DeleteHiddenValue(v8::String::New("_setter"));
        object.Dispose();
        object.Clear();
  }
}

TickHandler(SetAccessorTickHandler) {
  char aname[MAX_ATOM_LEN];
  const char *atom_val;
  val_res_t *obj_res;
  if (enif_get_resource(vm->env,array[1],val_resource,(void **)(&obj_res))) {
	LHCS(obj_res->ctx);

	if (arity > 3) {
	  v8::Handle<v8::Value> name = term_to_js(vm->env,array[2]);
	  if (!name->IsString()) {
          goto badarg;
      }
	  v8::AccessorGetter getter = GetterFun;
	  v8::AccessorSetter setter = 0;
	  v8::Persistent<v8::Object> data = v8::Persistent<v8::Object>::New(v8::Object::New());
	  data.MakeWeak(NULL,weak_accessor_data_cleaner); // so that we'll release externals when we're done

	  if (term_to_js(vm->env,array[3])->IsUndefined()) {
          goto badarg;
	  } else {
		data->SetHiddenValue(v8::String::New("_getter"), term_to_external(array[3]));
	  }

	  if (arity > 4) {
		setter = SetterFun;
		data->SetHiddenValue(v8::String::New("_setter"), term_to_external(array[4]));
	  }

	  v8::AccessControl access_control = v8::DEFAULT;

	  if (arity > 5 && enif_is_atom(vm->env, array[5])) {
		unsigned len;
		enif_get_atom_length(vm->env, array[5], &len, ERL_NIF_LATIN1);
		enif_get_atom(vm->env,array[5], (char *) &aname,len + 1, ERL_NIF_LATIN1);
		if (!strcmp(aname,"default")) {
		  access_control = v8::DEFAULT;
		} else if (!strcmp(aname,"all_can_read")) {
		  access_control = v8::ALL_CAN_READ;
		} else if (!strcmp(aname,"all_can_write")) {
		  access_control = v8::ALL_CAN_WRITE;
		} else if (!strcmp(aname,"prohibits_overwriting")) {
		  access_control = v8::PROHIBITS_OVERWRITING;
		}
	  }

	  v8::PropertyAttribute property_attribute = v8::None;

	  if (arity > 6) {
		property_attribute = term_to_property_attribute(vm->env,array[6]);
	  }

      atom_val = obj_res->val->ToObject()->SetAccessor(name->ToString(), getter, setter, data,
																   access_control, property_attribute) ? "true" : "false";
      goto send;
	}
badarg:
    atom_val = "badarg";
send:
	SEND(vm->server,
		 enif_make_tuple3(env,
						  enif_make_atom(env,"result"),
						  enif_make_copy(env,tick_ref),
						  enif_make_atom(env, atom_val)));
  }
  return DONE;
}

v8::Handle<v8::Value> GetterFun(v8::Local<v8::String> property,const v8::AccessorInfo &info) {
  v8::HandleScope handle_scope;
  VM * vm = (VM *)__ERLV8__(v8::Context::GetCurrent()->Global());

  v8::Local<v8::Object> data = info.Data()->ToObject();

  // each call gets a unique ref
  ERL_NIF_TERM ref = enif_make_ref(vm->env);

  // prepare arguments
  ERL_NIF_TERM *arr = (ERL_NIF_TERM *) malloc(sizeof(ERL_NIF_TERM) * 1);
  arr[0] = js_to_term(vm->env, property);
  ERL_NIF_TERM arglist = enif_make_list_from_array(vm->env,arr,1);
  free(arr);

  // send invocation request
  SEND(vm->server,
	   enif_make_tuple3(env,
						enif_make_copy(env,external_to_term(data->GetHiddenValue(v8::String::New("_getter")))),
						enif_make_tuple7(env,
										 enif_make_atom(env,"erlv8_fun_invocation"),
										 enif_make_atom(env,"false"),
										 js_to_term(env, info.Holder()),
										 js_to_term(env, info.This()),
										 enif_make_copy(env, ref),
										 enif_make_pid(env, vm->server),
										 enif_make_copy(env, external_to_term(v8::Context::GetCurrent()->Global()->GetHiddenValue(v8::String::New("__erlv8__ctx__"))))
										 ),
						enif_make_copy(env,arglist)));
  return vm->ticker(ref);
}

void SetterFun(v8::Local<v8::String> property,v8::Local<v8::Value> value,const v8::AccessorInfo &info) {
  v8::HandleScope handle_scope;
  VM * vm = (VM *)__ERLV8__(v8::Context::GetCurrent()->Global());

  v8::Local<v8::Object> data = info.Data()->ToObject();

  // each call gets a unique ref
  ERL_NIF_TERM ref = enif_make_ref(vm->env);

  // prepare arguments
  ERL_NIF_TERM *arr = (ERL_NIF_TERM *) malloc(sizeof(ERL_NIF_TERM) * 2);
  arr[0] = js_to_term(vm->env, property);
  arr[1] = js_to_term(vm->env, value);
  ERL_NIF_TERM arglist = enif_make_list_from_array(vm->env,arr,2);
  free(arr);

  // send invocation request
  SEND(vm->server,
	   enif_make_tuple3(env,
						enif_make_copy(env,external_to_term(data->GetHiddenValue(v8::String::New("_setter")))),
						enif_make_tuple7(env,
										 enif_make_atom(env,"erlv8_fun_invocation"),
										 enif_make_atom(env,"false"),
										 js_to_term(env, info.Holder()),
										 js_to_term(env, info.This()),
										 enif_make_copy(env, ref),
										 enif_make_pid(env, vm->server),
										 enif_make_copy(env, external_to_term(v8::Context::GetCurrent()->Global()->GetHiddenValue(v8::String::New("__erlv8__ctx__"))))
										 ),
						enif_make_copy(env,arglist)));
  vm->ticker(ref);
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// WindowSurfaceWGL.cpp: WGL implementation of egl::Surface for windows

#include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h"

#include "common/debug.h"
#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
#include "libANGLE/renderer/gl/wgl/wgl_utils.h"

namespace rx
{

WindowSurfaceWGL::WindowSurfaceWGL(EGLNativeWindowType window, ATOM windowClass, int pixelFormat, HGLRC wglContext, const FunctionsWGL *functions)
    : SurfaceGL(),
      mWindowClass(windowClass),
      mPixelFormat(pixelFormat),
      mShareWGLContext(wglContext),
      mParentWindow(window),
      mChildWindow(nullptr),
      mChildDeviceContext(nullptr),
      mFunctionsWGL(functions)
{
}

WindowSurfaceWGL::~WindowSurfaceWGL()
{
    mWindowClass = 0;
    mPixelFormat = 0;
    mShareWGLContext = nullptr;

    mFunctionsWGL->makeCurrent(mChildDeviceContext, nullptr);
    ReleaseDC(mChildWindow, mChildDeviceContext);
    mChildDeviceContext = nullptr;

    DestroyWindow(mChildWindow);
    mChildWindow = nullptr;
}

egl::Error WindowSurfaceWGL::initialize()
{
    // Create a child window of the supplied window to draw to.
    RECT rect;
    if (!GetClientRect(mParentWindow, &rect))
    {
        return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the size of the native window.");
    }

    mChildWindow = CreateWindowExA(WS_EX_NOPARENTNOTIFY,
                                   reinterpret_cast<const char*>(mWindowClass),
                                   "ANGLE Intermediate Surface Window",
                                   WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE,
                                   0,
                                   0,
                                   rect.right - rect.left,
                                   rect.bottom - rect.top,
                                   mParentWindow,
                                   NULL,
                                   NULL,
                                   NULL);
    if (!mChildWindow)
    {
        return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to create a child window.");
    }

    mChildDeviceContext = GetDC(mChildWindow);
    if (!mChildDeviceContext)
    {
        return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the device context of the child window.");
    }

    const PIXELFORMATDESCRIPTOR pixelFormatDescriptor = wgl::GetDefaultPixelFormatDescriptor();

    if (!SetPixelFormat(mChildDeviceContext, mPixelFormat, &pixelFormatDescriptor))
    {
        return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to set the pixel format on the child window.");
    }

    return egl::Error(EGL_SUCCESS);
}

egl::Error WindowSurfaceWGL::makeCurrent()
{
    if (!mFunctionsWGL->makeCurrent(mChildDeviceContext, mShareWGLContext))
    {
        // TODO: What error type here?
        return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current.");
    }

    return egl::Error(EGL_SUCCESS);
}

egl::Error WindowSurfaceWGL::swap()
{
    // Resize the child window to the interior of the parent window.
    RECT rect;
    if (!GetClientRect(mParentWindow, &rect))
    {
        // TODO: What error type here?
        return egl::Error(EGL_CONTEXT_LOST, "Failed to get the size of the native window.");
    }

    if (!MoveWindow(mChildWindow, 0, 0, rect.right - rect.left, rect.bottom - rect.top, FALSE))
    {
        // TODO: What error type here?
        return egl::Error(EGL_CONTEXT_LOST, "Failed to move the child window.");
    }

    if (!mFunctionsWGL->swapBuffers(mChildDeviceContext))
    {
        // TODO: What error type here?
        return egl::Error(EGL_CONTEXT_LOST, "Failed to swap buffers on the child window.");
    }

    return egl::Error(EGL_SUCCESS);
}

egl::Error WindowSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
{
    UNIMPLEMENTED();
    return egl::Error(EGL_SUCCESS);
}

egl::Error WindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
{
    UNIMPLEMENTED();
    return egl::Error(EGL_SUCCESS);
}

egl::Error WindowSurfaceWGL::bindTexImage(EGLint buffer)
{
    UNIMPLEMENTED();
    return egl::Error(EGL_SUCCESS);
}

egl::Error WindowSurfaceWGL::releaseTexImage(EGLint buffer)
{
    UNIMPLEMENTED();
    return egl::Error(EGL_SUCCESS);
}

void WindowSurfaceWGL::setSwapInterval(EGLint interval)
{
    if (mFunctionsWGL->swapIntervalEXT)
    {
        mFunctionsWGL->swapIntervalEXT(interval);
    }
}

EGLint WindowSurfaceWGL::getWidth() const
{
    RECT rect;
    if (!GetClientRect(mParentWindow, &rect))
    {
        return 0;
    }
    return rect.right - rect.left;
}

EGLint WindowSurfaceWGL::getHeight() const
{
    RECT rect;
    if (!GetClientRect(mParentWindow, &rect))
    {
        return 0;
    }
    return rect.bottom - rect.top;
}

EGLint WindowSurfaceWGL::isPostSubBufferSupported() const
{
    // PostSubBuffer extension not exposed on WGL.
    UNIMPLEMENTED();
    return EGL_FALSE;
}

}
<commit_msg>Don't set a null current WGL context in the Surface destructor.<commit_after>//
// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// WindowSurfaceWGL.cpp: WGL implementation of egl::Surface for windows

#include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h"

#include "common/debug.h"
#include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
#include "libANGLE/renderer/gl/wgl/wgl_utils.h"

namespace rx
{

WindowSurfaceWGL::WindowSurfaceWGL(EGLNativeWindowType window, ATOM windowClass, int pixelFormat, HGLRC wglContext, const FunctionsWGL *functions)
    : SurfaceGL(),
      mWindowClass(windowClass),
      mPixelFormat(pixelFormat),
      mShareWGLContext(wglContext),
      mParentWindow(window),
      mChildWindow(nullptr),
      mChildDeviceContext(nullptr),
      mFunctionsWGL(functions)
{
}

WindowSurfaceWGL::~WindowSurfaceWGL()
{
    mWindowClass = 0;
    mPixelFormat = 0;
    mShareWGLContext = nullptr;

    ReleaseDC(mChildWindow, mChildDeviceContext);
    mChildDeviceContext = nullptr;

    DestroyWindow(mChildWindow);
    mChildWindow = nullptr;
}

egl::Error WindowSurfaceWGL::initialize()
{
    // Create a child window of the supplied window to draw to.
    RECT rect;
    if (!GetClientRect(mParentWindow, &rect))
    {
        return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the size of the native window.");
    }

    mChildWindow = CreateWindowExA(WS_EX_NOPARENTNOTIFY,
                                   reinterpret_cast<const char*>(mWindowClass),
                                   "ANGLE Intermediate Surface Window",
                                   WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE,
                                   0,
                                   0,
                                   rect.right - rect.left,
                                   rect.bottom - rect.top,
                                   mParentWindow,
                                   NULL,
                                   NULL,
                                   NULL);
    if (!mChildWindow)
    {
        return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to create a child window.");
    }

    mChildDeviceContext = GetDC(mChildWindow);
    if (!mChildDeviceContext)
    {
        return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to get the device context of the child window.");
    }

    const PIXELFORMATDESCRIPTOR pixelFormatDescriptor = wgl::GetDefaultPixelFormatDescriptor();

    if (!SetPixelFormat(mChildDeviceContext, mPixelFormat, &pixelFormatDescriptor))
    {
        return egl::Error(EGL_BAD_NATIVE_WINDOW, "Failed to set the pixel format on the child window.");
    }

    return egl::Error(EGL_SUCCESS);
}

egl::Error WindowSurfaceWGL::makeCurrent()
{
    if (!mFunctionsWGL->makeCurrent(mChildDeviceContext, mShareWGLContext))
    {
        // TODO: What error type here?
        return egl::Error(EGL_CONTEXT_LOST, "Failed to make the WGL context current.");
    }

    return egl::Error(EGL_SUCCESS);
}

egl::Error WindowSurfaceWGL::swap()
{
    // Resize the child window to the interior of the parent window.
    RECT rect;
    if (!GetClientRect(mParentWindow, &rect))
    {
        // TODO: What error type here?
        return egl::Error(EGL_CONTEXT_LOST, "Failed to get the size of the native window.");
    }

    if (!MoveWindow(mChildWindow, 0, 0, rect.right - rect.left, rect.bottom - rect.top, FALSE))
    {
        // TODO: What error type here?
        return egl::Error(EGL_CONTEXT_LOST, "Failed to move the child window.");
    }

    if (!mFunctionsWGL->swapBuffers(mChildDeviceContext))
    {
        // TODO: What error type here?
        return egl::Error(EGL_CONTEXT_LOST, "Failed to swap buffers on the child window.");
    }

    return egl::Error(EGL_SUCCESS);
}

egl::Error WindowSurfaceWGL::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
{
    UNIMPLEMENTED();
    return egl::Error(EGL_SUCCESS);
}

egl::Error WindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
{
    UNIMPLEMENTED();
    return egl::Error(EGL_SUCCESS);
}

egl::Error WindowSurfaceWGL::bindTexImage(EGLint buffer)
{
    UNIMPLEMENTED();
    return egl::Error(EGL_SUCCESS);
}

egl::Error WindowSurfaceWGL::releaseTexImage(EGLint buffer)
{
    UNIMPLEMENTED();
    return egl::Error(EGL_SUCCESS);
}

void WindowSurfaceWGL::setSwapInterval(EGLint interval)
{
    if (mFunctionsWGL->swapIntervalEXT)
    {
        mFunctionsWGL->swapIntervalEXT(interval);
    }
}

EGLint WindowSurfaceWGL::getWidth() const
{
    RECT rect;
    if (!GetClientRect(mParentWindow, &rect))
    {
        return 0;
    }
    return rect.right - rect.left;
}

EGLint WindowSurfaceWGL::getHeight() const
{
    RECT rect;
    if (!GetClientRect(mParentWindow, &rect))
    {
        return 0;
    }
    return rect.bottom - rect.top;
}

EGLint WindowSurfaceWGL::isPostSubBufferSupported() const
{
    // PostSubBuffer extension not exposed on WGL.
    UNIMPLEMENTED();
    return EGL_FALSE;
}

}
<|endoftext|>


<commit_before>// -------------------------------------------------------------------
//
// leo_erasure: Erasure code library for Erlang
//
// Copyright (c) 2012-2015 Rakuten, Inc.
//
// This file is provided to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file
// except in compliance with the License.  You may obtain
// a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
//
// -------------------------------------------------------------------
#include <string.h>
#include <set>

#include "rscoding.h"
#include "jerasure.h"
#include "jerasure_mod.h"
#include "reed_sol.h"

void RSCoding::checkParams() {
    if (k <= 0 || m <= 0 || w <= 0)
        throw std::invalid_argument("Invalid Coding Parameters");
	if (w != 8 && w != 16 && w != 32)
        throw std::invalid_argument("Invalid Coding Parameters (w = 8/16/32)");
}

vector<ERL_NIF_TERM> RSCoding::doEncode(ERL_NIF_TERM dataBin) {
    int *matrix = reed_sol_vandermonde_coding_matrix(k, m, w);
    char* dataBlocks[k];
    char* codeBlocks[m];

    ErlNifBinary data;
    enif_inspect_binary(env, dataBin, &data);

    size_t dataSize = data.size;
    size_t blockSize = roundTo((roundTo(dataSize, k*w) / (k*w)), 16) * w;

    size_t offset = 0;
    size_t remain = dataSize;
    int filled = 0;
    while(remain >= blockSize) {
        dataBlocks[filled] = (char*)data.data + offset;
        offset += blockSize;
        remain -= blockSize;
        filled++;
    }
    ErlNifBinary tmp;
    enif_alloc_binary((k + m - filled) * blockSize + 16, &tmp);
    size_t align = (((size_t)data.data & 0x0f) - ((size_t)tmp.data & 0x0f) + 16) & 0x0f;
    char* alignedHead = (char*)tmp.data + align;
    memcpy(alignedHead, data.data + filled * blockSize, dataSize - filled * blockSize);
    offset = 0;
    for(int i = filled; i < k + m; ++i, offset += blockSize) {
        (i < k) ? dataBlocks[i] = alignedHead + offset:
            codeBlocks[i - k] = alignedHead + offset;
    }

    jerasure_matrix_encode(k, m, w, matrix, dataBlocks, codeBlocks, blockSize);

    vector<ERL_NIF_TERM> blockList;
    for(int i = 0; i < filled; ++i) {
        blockList.push_back(enif_make_sub_binary(env, dataBin, i * blockSize, blockSize));
    }
    ERL_NIF_TERM tmpBin = enif_make_binary(env, &tmp);
    offset = 0;
    for(int i = filled; i < k + m; ++i, offset += blockSize) {
        blockList.push_back(enif_make_sub_binary(env, tmpBin, offset + align, blockSize));
    }

    free(matrix);
    return blockList;
}

ERL_NIF_TERM RSCoding::doDecode(vector<ERL_NIF_TERM> blockList, vector<int> blockIdList, size_t dataSize) {

    set<int> availSet(blockIdList.begin(), blockIdList.end());
    if (availSet.size() < (unsigned int)k)
        throw std::invalid_argument("Not Enough Blocks");
    else if (availSet.size() < blockIdList.size()) {
        throw std::invalid_argument("Blocks should be unique");
    }

    size_t blockSize;

    ErlNifBinary blocks[k + m];
    for(size_t i = 0; i < blockIdList.size(); ++i) {
        int blockId = blockIdList[i];
        enif_inspect_binary(env, blockList[i], &blocks[blockId]);
        blockSize = blocks[blockId].size;
    }

    bool needFix = false;

    for(int i = 0; i < k; ++i)
        if (availSet.count(i) == 0) {
            needFix = true;
        }

    if (!needFix) {
        ErlNifBinary file;
        enif_alloc_binary(dataSize, &file);
        size_t copySize, offset = 0;
        for(int i = 0; i < k; ++i) {
            offset = i * blockSize;
            copySize = min(dataSize - offset, blockSize);
            memcpy(file.data + offset, blocks[i].data, copySize);
        }
        ERL_NIF_TERM bin = enif_make_binary(env, &file);
        return bin;
    }

    char* dataBlocks[k];
    char* codeBlocks[m];
    int erasures[k + m];
    ErlNifBinary tmpBin;
    enif_alloc_binary(blockSize * (k + m), &tmpBin);
    char* tmpMemory = (char*)tmpBin.data;

    int j = 0;
    for(int i = 0; i < k + m; ++i) {
        i < k ? dataBlocks[i] = tmpMemory + i * blockSize : codeBlocks[i - k] = tmpMemory + i * blockSize;
        if (availSet.count(i) == 0) {
            erasures[j++] = i;
        } else {
            memcpy(tmpMemory + i * blockSize, blocks[i].data, blockSize);
        }
    }
    erasures[j] = -1;

    int *matrix = reed_sol_vandermonde_coding_matrix(k, m, w);
    jerasure_matrix_decode_data(k, m, w, matrix, 1, erasures, dataBlocks, codeBlocks, blockSize);

    ERL_NIF_TERM allBlocksBin = enif_make_binary(env, &tmpBin);
    ERL_NIF_TERM bin = enif_make_sub_binary(env, allBlocksBin, 0, dataSize);

    free(matrix);
    return bin;
}

vector<ERL_NIF_TERM> RSCoding::doRepair(vector<ERL_NIF_TERM> blockList, vector<int> blockIdList, vector<int> repairList) {

    set<int> availSet(blockIdList.begin(), blockIdList.end());
    if (availSet.size() < (unsigned int)k)
        throw std::invalid_argument("Not Enough Blocks");
    else if (availSet.size() < blockIdList.size()) {
        throw std::invalid_argument("Blocks should be unique");
    }

    size_t blockSize;

    ErlNifBinary blocks[k + m];
    for(size_t i = 0; i < blockIdList.size(); ++i) {
        int blockId = blockIdList[i];
        enif_inspect_binary(env, blockList[i], &blocks[blockId]);
        blockSize = blocks[blockId].size;
    }

    char* dataBlocks[k];
    char* codeBlocks[m];
    int erasures[k + m];
    ErlNifBinary tmpBin;
    enif_alloc_binary(blockSize * (k + m), &tmpBin);
    char* tmpMemory = (char*)tmpBin.data;

    int j = 0;
    for(int i = 0; i < k + m; ++i) {
        i < k ? dataBlocks[i] = tmpMemory + i * blockSize : codeBlocks[i - k] = tmpMemory + i * blockSize;
        if (availSet.count(i) == 0) {
            erasures[j++] = i;
        } else {
            memcpy(tmpMemory + i * blockSize, blocks[i].data, blockSize);
        }
    }
    erasures[j] = -1;

    repairList.push_back(-1);
    int *selected = &repairList[0];
    int *matrix = reed_sol_vandermonde_coding_matrix(k, m, w);
    jerasure_matrix_decode_selected(k, m, w, matrix, 1, erasures, selected, dataBlocks, codeBlocks, blockSize);

    vector<ERL_NIF_TERM> repairBlocks;
    int repairId;
    ERL_NIF_TERM allBlocksBin = enif_make_binary(env, &tmpBin);
    for(size_t i = 0; i < repairList.size() - 1; ++i) {
        repairId = repairList[i];
        ERL_NIF_TERM block = enif_make_sub_binary(env, allBlocksBin, repairId * blockSize, blockSize);
        repairBlocks.push_back(block);
    }

    free(matrix);
    return repairBlocks;
}
<commit_msg>[Backend] Added error handling for matrix generation<commit_after>// -------------------------------------------------------------------
//
// leo_erasure: Erasure code library for Erlang
//
// Copyright (c) 2012-2015 Rakuten, Inc.
//
// This file is provided to you under the Apache License,
// Version 2.0 (the "License"); you may not use this file
// except in compliance with the License.  You may obtain
// a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.
//
// -------------------------------------------------------------------
#include <string.h>
#include <set>

#include "rscoding.h"
#include "jerasure.h"
#include "jerasure_mod.h"
#include "reed_sol.h"

void RSCoding::checkParams() {
    if (k <= 0 || m <= 0 || w <= 0)
        throw std::invalid_argument("Invalid Coding Parameters");
	if (w != 8 && w != 16 && w != 32)
        throw std::invalid_argument("Invalid Coding Parameters (w = 8/16/32)");
}

vector<ERL_NIF_TERM> RSCoding::doEncode(ERL_NIF_TERM dataBin) {
    char* dataBlocks[k];
    char* codeBlocks[m];

    ErlNifBinary data;
    enif_inspect_binary(env, dataBin, &data);

    size_t dataSize = data.size;
    size_t blockSize = roundTo((roundTo(dataSize, k*w) / (k*w)), 16) * w;

    size_t offset = 0;
    size_t remain = dataSize;
    int filled = 0;
    while(remain >= blockSize) {
        dataBlocks[filled] = (char*)data.data + offset;
        offset += blockSize;
        remain -= blockSize;
        filled++;
    }
    ErlNifBinary tmp;
    enif_alloc_binary((k + m - filled) * blockSize + 16, &tmp);
    size_t align = (((size_t)data.data & 0x0f) - ((size_t)tmp.data & 0x0f) + 16) & 0x0f;
    char* alignedHead = (char*)tmp.data + align;
    memcpy(alignedHead, data.data + filled * blockSize, dataSize - filled * blockSize);
    offset = 0;
    for(int i = filled; i < k + m; ++i, offset += blockSize) {
        (i < k) ? dataBlocks[i] = alignedHead + offset:
            codeBlocks[i - k] = alignedHead + offset;
    }

    int *matrix = reed_sol_vandermonde_coding_matrix(k, m, w);
    if (!matrix) {
        throw new std::bad_alloc();
    }
    jerasure_matrix_encode(k, m, w, matrix, dataBlocks, codeBlocks, blockSize);

    vector<ERL_NIF_TERM> blockList;
    for(int i = 0; i < filled; ++i) {
        blockList.push_back(enif_make_sub_binary(env, dataBin, i * blockSize, blockSize));
    }
    ERL_NIF_TERM tmpBin = enif_make_binary(env, &tmp);
    offset = 0;
    for(int i = filled; i < k + m; ++i, offset += blockSize) {
        blockList.push_back(enif_make_sub_binary(env, tmpBin, offset + align, blockSize));
    }

    free(matrix);
    return blockList;
}

ERL_NIF_TERM RSCoding::doDecode(vector<ERL_NIF_TERM> blockList, vector<int> blockIdList, size_t dataSize) {

    set<int> availSet(blockIdList.begin(), blockIdList.end());
    if (availSet.size() < (unsigned int)k)
        throw std::invalid_argument("Not Enough Blocks");
    else if (availSet.size() < blockIdList.size()) {
        throw std::invalid_argument("Blocks should be unique");
    }

    size_t blockSize;

    ErlNifBinary blocks[k + m];
    for(size_t i = 0; i < blockIdList.size(); ++i) {
        int blockId = blockIdList[i];
        enif_inspect_binary(env, blockList[i], &blocks[blockId]);
        blockSize = blocks[blockId].size;
    }

    bool needFix = false;

    for(int i = 0; i < k; ++i)
        if (availSet.count(i) == 0) {
            needFix = true;
        }

    if (!needFix) {
        ErlNifBinary file;
        enif_alloc_binary(dataSize, &file);
        size_t copySize, offset = 0;
        for(int i = 0; i < k; ++i) {
            offset = i * blockSize;
            copySize = min(dataSize - offset, blockSize);
            memcpy(file.data + offset, blocks[i].data, copySize);
        }
        ERL_NIF_TERM bin = enif_make_binary(env, &file);
        return bin;
    }

    char* dataBlocks[k];
    char* codeBlocks[m];
    int erasures[k + m];
    ErlNifBinary tmpBin;
    enif_alloc_binary(blockSize * (k + m), &tmpBin);
    char* tmpMemory = (char*)tmpBin.data;

    int j = 0;
    for(int i = 0; i < k + m; ++i) {
        i < k ? dataBlocks[i] = tmpMemory + i * blockSize : codeBlocks[i - k] = tmpMemory + i * blockSize;
        if (availSet.count(i) == 0) {
            erasures[j++] = i;
        } else {
            memcpy(tmpMemory + i * blockSize, blocks[i].data, blockSize);
        }
    }
    erasures[j] = -1;

    int *matrix = reed_sol_vandermonde_coding_matrix(k, m, w);
    if (!matrix) {
        throw new std::bad_alloc();
    }
    jerasure_matrix_decode_data(k, m, w, matrix, 1, erasures, dataBlocks, codeBlocks, blockSize);

    ERL_NIF_TERM allBlocksBin = enif_make_binary(env, &tmpBin);
    ERL_NIF_TERM bin = enif_make_sub_binary(env, allBlocksBin, 0, dataSize);

    free(matrix);
    return bin;
}

vector<ERL_NIF_TERM> RSCoding::doRepair(vector<ERL_NIF_TERM> blockList, vector<int> blockIdList, vector<int> repairList) {

    set<int> availSet(blockIdList.begin(), blockIdList.end());
    if (availSet.size() < (unsigned int)k)
        throw std::invalid_argument("Not Enough Blocks");
    else if (availSet.size() < blockIdList.size()) {
        throw std::invalid_argument("Blocks should be unique");
    }

    size_t blockSize;

    ErlNifBinary blocks[k + m];
    for(size_t i = 0; i < blockIdList.size(); ++i) {
        int blockId = blockIdList[i];
        enif_inspect_binary(env, blockList[i], &blocks[blockId]);
        blockSize = blocks[blockId].size;
    }

    char* dataBlocks[k];
    char* codeBlocks[m];
    int erasures[k + m];
    ErlNifBinary tmpBin;
    enif_alloc_binary(blockSize * (k + m), &tmpBin);
    char* tmpMemory = (char*)tmpBin.data;

    int j = 0;
    for(int i = 0; i < k + m; ++i) {
        i < k ? dataBlocks[i] = tmpMemory + i * blockSize : codeBlocks[i - k] = tmpMemory + i * blockSize;
        if (availSet.count(i) == 0) {
            erasures[j++] = i;
        } else {
            memcpy(tmpMemory + i * blockSize, blocks[i].data, blockSize);
        }
    }
    erasures[j] = -1;

    repairList.push_back(-1);
    int *selected = &repairList[0];
    int *matrix = reed_sol_vandermonde_coding_matrix(k, m, w);
    if (!matrix) {
        throw new std::bad_alloc();
    }
    jerasure_matrix_decode_selected(k, m, w, matrix, 1, erasures, selected, dataBlocks, codeBlocks, blockSize);

    vector<ERL_NIF_TERM> repairBlocks;
    int repairId;
    ERL_NIF_TERM allBlocksBin = enif_make_binary(env, &tmpBin);
    for(size_t i = 0; i < repairList.size() - 1; ++i) {
        repairId = repairList[i];
        ERL_NIF_TERM block = enif_make_sub_binary(env, allBlocksBin, repairId * blockSize, blockSize);
        repairBlocks.push_back(block);
    }

    free(matrix);
    return repairBlocks;
}
<|endoftext|>