RX - how to use it in a performant way?

Viewed 506

I am trying to understand how to structure my program to use RX in a performant matter.
My app has a vector of objects in the 3D world. each object occupied a box, and have a 'hit' stream, which represent a mouse hover over it.
I thought of two options of how to structure:

Option 1

struct object_t
{
  string name_;
  box bounding_box_;
  observable<bool> hit_;
};

struct scene_t
{
  scene_t(observable<point> mouse) : hit_(hit(mouse)) 
  {
    add({"background", {/* ... */}, {}};
  }

  object_t& add(object_t o)
  {
    int object_index = objects_.size();
    o.hit_ = hit_
             .map([=](int index){ return index == object_index; })
             .distinct_until_changed();
    objects_.push_back(o);
    return objects_.back();
  }

  //! given a stream of mouse points,
  //! calculate on which object index(in objects_) the mouse is hover over. 
  //! 0 if its over the background. 
  observable<int> hit(observable<point> mouse);

  using objects_t = std::vector<object_t>;
  objects_t objects_; 
  observable<int> hit_
};

Option 2

struct object_t
{
  string name_;
  box bounding_box_;

  void signal_hit(boot is_hit) { hit_.get_observer().on_next(is_hit); }

  observable<bool> hit() const { return hit_.get_observable(); }

private:
  subject<bool> hit_;
};

struct scene_t
{
  scene_t(observable<point> mouse) : hit_(hit(mouse)) 
  {
    add({"background", {/* ... */}, {}};
    hit_
       .start_with(0)
       .buffer(2, 1) // take two hits together, the current and the previos
       .subscribe([this](std::vector<int> indices) {
          objects_[indices[1]].signal_hit(false); // we leave this one 
          objects_[indices[0]].signal_hit(true); // and entering this one
        });        
  }

  object_t& add(object_t o)
  {
    objects_.push_back(o);
    return objects_.back();
  }
  //! ... as above
};

Now the question is how to chain the result of the hit function to the object_t::hit stream.
I see two ways:

  1. Option 1, is fully functional, but very poorly performing, since for every mouse point, all objects stream will need to calculate their value.
  2. Option 2. is not fully functional, as I use subject to push the values to the right stream, in an imperative way. but is very performant as only the right (two) object(s) hit stream get to fire.

Note: The implementation is in rxcpp, but its general to any language we have RX in it, or general FRP paradigm, this is why I tagged rxjs\rx.net\frp etc.
thanks in advance :-)

1 Answers
Related