Multi-threaded Text Insertion into a TextView



Hello,

I'm using gtkmm-2.4.2.
I have several POSIX threads trying to insert text into a Textview. So, I use a POSIX mutex to be sure that text is inserted into the TextBuffer one after the other.

Most of time, it works but sometimes, I get some GTK error message :

(TTdaq Application v0.8b:16046): Gtk-WARNING **: Invalid text buffer iterator: either the iterator is uninitialized, or the characters/pixbufs/widgets in the buffer have been modified since the iterator was created.
You must use marks, character numbers, or line numbers to preserve a position across buffer modifications.
You can apply tags and insert marks without invalidating your iterators,
but any mutation that affects 'indexable' buffer contents (contents that can be referred to by character offset)
will invalidate all outstanding iterators

(TTdaq Application v0.8b:16419): Gtk-CRITICAL **: file gtktextlayout.c: line 813 (gtk_text_layout_real_invalidate): assertion `layout->wrap_loop_count == 0' failed

(TTdaq Application v0.8b:18972): Gtk-CRITICAL **: file gtktextlayout.c: line 813 (gtk_text_layout_real_invalidate): assertion `layout->wrap_loop_count == 0' failed

(TTdaq Application v0.8b:18510): Gtk-CRITICAL **: file gtktextbuffer.c: line 1810 (gtk_text_buffer_get_iter_at_mark): assertion `!gtk_text_mark_get_deleted (mark)' failed

And sometimes... it crashes with a "Segmentation Fault".

I have already tried different implementation which doesn't work better ;-) !
One of them was to fill a std::queue and create a Glib thread for re-read it, and insert the messages into the Textview (a kind of producer/consummer)... But it crashes even more often !

Here is extracts of my application:

  enum LogType
  {
    INFO,
    WARNING,
    ERROR
  };

  // This function is used by the different threads !
  void add(LogType l, std::string msg)
  {
    pthread_mutex_lock(&pmut_log_update);

    switch(l)
    {
       case INFO:
    globalControlWidget->printInfoLog(msg);
    break;
       case WARNING:
    globalControlWidget->printWarningLog(msg);
    break;
       case ERROR:
    globalControlWidget->printErrorLog(msg);
    break;
    }
   
    pthread_mutex_unlock(&pmut_log_update); 
  }
 
  ....
  /************************************************************/
  // The class GlobalControlWidget
 
  class GlobalControlWidget : public Gtk::VBox
  {
Gtk::TextView *logText;
Gtk::ScrolledWindow *logScrolledwindow;
Glib::RefPtr<Gtk::TextBuffer> refTextLogBuffer;
Glib::RefPtr<Gtk::TextBuffer::Tag> refTagError;
Glib::RefPtr<Gtk::TextBuffer::Tag> refTagWarning;
Glib::RefPtr<Gtk::TextBuffer::TagTable> refTagTable;
void scrollLogView();
    public:
        GlobalControlWidget(TTdaqMainWindow*);    
        ~GlobalControlWidget();
void printInfoLog(const std::string &);
void printErrorLog(const std::string &);
void printWarningLog(const std::string &);
void updateStartStopBoutonsSensitivity();
  };


 
  GlobalControlWidget::GlobalControlWidget()
  {
   logText = manage(new class Gtk::TextView());
   logText->set_flags(Gtk::CAN_FOCUS);
   logText->set_editable(false);
   //refTextLogBuffer = Gtk::TextBuffer::create();
   //logText->set_buffer(refTextLogBuffer);
   refTextLogBuffer=logText->get_buffer();

   refTextLogBuffer->signal_changed().connect( sigc::mem_fun(*this, &GlobalControlWidget::scrollLogView));

   //Create a TagTable:
   refTagTable = refTextLogBuffer->get_tag_table();

   //Apply color to some text.
   //Create the tags:
   refTagWarning = Gtk::TextBuffer::Tag::create("Warning_Message"); //We give it an arbitrary name.
   refTagWarning->property_background() = "orange";
   refTagTable->add(refTagWarning);
   refTagError = Gtk::TextBuffer::Tag::create("Error_Message"); //We give it an arbitrary name.
   refTagError->property_background() = "red";
   refTagTable->add(refTagError);
  
   logScrolledwindow = manage(new class Gtk::ScrolledWindow());
   logScrolledwindow->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_ALWAYS);
   logScrolledwindow->add(*logText); 
   Gtk::Frame *logFrame = manage(new class Gtk::Frame("Log"));
   logFrame->set_shadow_type(Gtk::SHADOW_ETCHED_IN);
   logFrame->set_label_align(0,0);
   logFrame->add(*logScrolledwindow);
  
   pack_start(*logFrame, true, true, 5);
   show_all_children();
   show();
   set_redraw_on_allocate(true);
  }
 
  void GlobalControlWidget::printInfoLog(const std::string &msg)
  {
    refTextLogBuffer->insert(refTextLogBuffer->end(), msg+"\n");
  }

  void GlobalControlWidget::printErrorLog(const std::string &msg)
  {
    refTextLogBuffer->insert_with_tag(refTextLogBuffer->end(), msg+"\n", refTagError);
  }

  void GlobalControlWidget::printWarningLog(const std::string &msg)
  {
    refTextLogBuffer->insert_with_tag(refTextLogBuffer->end(), msg+"\n", refTagWarning);
  }

  void GlobalControlWidget::scrollLogView()
  {
    logText->scroll_mark_onscreen( refTextLogBuffer->get_insert() );
  }
 
Pleeaasse heelllpp !!!
Cheers,
DESCOMBES Thierry

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]