lundi 19 mars 2018

Changes made within a member function cannot be seen outside its scope

I'm using a library which requires me to derive from a class it provides and then override a function. However, I'm facing a strange situation where changes made within the member function are:

  • Temporary: they last only in the scope of the member function.
  • Non-persistent: In an iteration, the changes made in previous iterations are not visible.

For example, if I have a global int variable initialized to 0 which I increment in the member function, it's value pre-increment is 0 and 1 post-increment while within the member function, but always 0 outside the function's scope. Here is an example that demonstrates the problem:

#include <iostream>
#include <thread>
#include <gtkmm.h>
#include <xmlrpc-c/base.hpp>
#include <xmlrpc-c/registry.hpp>
#include <xmlrpc-c/server_abyss.hpp>

class TestWindow : public Gtk::Window {
public:
  TestWindow();
  // Called from worker thread
  void notify(void (*callback)());
  //Dispatcher handler
  void on_notification_from_worker_thread();
  //Data
  Glib::Dispatcher m_Dispatcher;
  //Callback functions
  void (*on_notify_callback)();
};

class RpcWorker {
public:
  RpcWorker(TestWindow* nw);
  TestWindow* window;
  RpcWorker* worker;
  void start_thread ();
};

RpcWorker::RpcWorker(TestWindow* nw){
  window = nw;
}

void foo (){
  std::cout << "Foo called" << std::endl;
}

void bar (){
  std::cout << "Bar called" << std::endl;
}

class testFunction : public xmlrpc_c::method {
public:
  testFunction(TestWindow* nw, RpcWorker* worker);
  TestWindow* window;
  RpcWorker* worker;
  void execute(xmlrpc_c::paramList const& paramList,
               xmlrpc_c::value *   const  retvalP) {
    window->notify(bar);
    *retvalP = xmlrpc_c::value_int(0);
  }
};

testFunction::testFunction(TestWindow* nw, RpcWorker* wk){
  window = nw;
  worker = wk;
}

void RpcWorker::start_thread() {
  std::cout << "Thread started" << std::endl;
  xmlrpc_c::registry myRegistry;
  xmlrpc_c::methodPtr const testFunctionP(new testFunction(window, this));
  myRegistry.addMethod("next.hideMinibuffer", testFunctionP);
  xmlrpc_c::serverAbyss myAbyssServer (myRegistry, 8080, "/tmp/xmlrpc_log");
  myAbyssServer.run();
}

TestWindow::TestWindow(){
  m_Dispatcher.connect(sigc::mem_fun
                       (*this, &TestWindow::on_notification_from_worker_thread));
  on_notify_callback = foo;
}

void TestWindow::notify(void (*callback)()) {
  on_notify_callback = callback;
  m_Dispatcher.emit();
}

void TestWindow::on_notification_from_worker_thread() {
  on_notify_callback();
}

int main(int argc, char *argv[]){
  auto app = Gtk::Application::create(argc, argv, "Test.Window");
  TestWindow window;
  RpcWorker worker = RpcWorker(&window);
  std::thread* rpc_worker_thread = new std::thread(&RpcWorker::start_thread, &worker);
  return app->run(window);
}

What is causing this situation, and how do I fix it or work around it?

Aucun commentaire:

Enregistrer un commentaire