Re: How to properly exit a thread?




Xiangfei,

Not quite...

I've made a couple changes to your code below. I haven't compiled/tested this at all, but just wanted to describe what you should be doing. I'd recommend adding accessor mutators for FrameNode.

Hope it helps.

Xiangfei Jia wrote:

Hi, Paul:

I'm writing a GUI for monitoring system memory and swap disks. Basically, I created a thread to read the "/proc/meminfo" continueously and put new data into the customised DrawingArea class to plot memory graph every second.

It works like everytime the thread read a new data, the thread will wait until the customised DrawingArea class finished ploting the new data and then signal the thread to read more data.

I haven't used gtkmm for long, and not so clear about how to use gtkmm-wrapped threads. I tried to used your method, still now working. Probably, I didn't use it properly.

I did like this:
try {
Glib::Thread *const read = Glib::Thread::create(sigc::mem_fun(node, &FrameNode::read_new_data), false);
 } catch(Glib::Thread::Exit&) {
   // Just exit from the thread.  The Thread::Exit exception
   // is our sane C++ replacement of g_thread_exit().
 }
 catch(...)
 {
   Glib::exception_handlers_invoke();
 }

This is source code in Glib. You're not supposed to included it in your code.

To make things clear, I attated my source code.

Thanks!!!

Fei

------------------------------------------------------------------------


#ifndef FRAMENODE_H
#define FRAMENODE_H

#include <gtkmm.h>
#include <fstream>
#include "DisplayPlot.h"

class FrameNode : public Gtk::Frame {

public:
   FrameNode(char *);
   ~FrameNode();
   Gtk::HBox hbox_top;
   Gdk::Color temp_;
   DisplayPlot *plot_mem;
   DisplayPlot *plot_swap;

         bool TIME_TO_DIE ;

	Glib::Mutex mutex_;
	Glib::Cond cond_drawing_;

	void read_new_data();
	bool update_plot();

private:
   Gtk::Label *label_mem_total, *label_mem_free, *label_mem_used;
   Gtk::Label *label_swap_total, *label_swap_free;
	bool finished_drawing;
	bool finished_adding_new_data;
	char filename[100];
};

#endif
------------------------------------------------------------------------


#include "FrameNode.h"
#include <libglademm/xml.h>
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <fstream>
#include <cstdlib>

FrameNode::FrameNode(char *fname) :
   hbox_top(false, 0)
{
         TIME_TO_DIE = false ;

   set_label(" Hostname: Local ");
   //set_shadow_type(Gtk::SHADOW_OUT);
   //set_border_width(10);
   Glib::RefPtr<Gnome::Glade::Xml> refXml = Gnome::Glade::Xml::create("./monitor-temp.glade");
   Gtk::EventBox *eventbox;
   refXml->get_widget("eventbox1", eventbox);

	eventbox->reparent(*this);

	//plot mem
	plot_mem = Gtk::manage(new DisplayPlot);
   Gtk::VBox *vbox_plot;
	refXml->get_widget("vbox_plot_mem_container", vbox_plot);
	vbox_plot->pack_start(*plot_mem, Gtk::PACK_SHRINK, 0);

	refXml->get_widget("label_mem_total", label_mem_total);
	refXml->get_widget("label_mem_free", label_mem_free);
	refXml->get_widget("label_mem_used", label_mem_used);

	//plot swap
	plot_swap = Gtk::manage(new DisplayPlot);
	refXml->get_widget("vbox_plot_swap_container", vbox_plot);
	vbox_plot->pack_start(*plot_swap, Gtk::PACK_SHRINK, 0);

	refXml->get_widget("label_swap_total", label_swap_total);
	refXml->get_widget("label_swap_free", label_swap_free);

	strcpy(filename, fname);
	finished_drawing = true;
	finished_adding_new_data = false;
	Glib::signal_timeout().connect(sigc::mem_fun(*this, &FrameNode::update_plot), 1000);


}

void FrameNode::read_new_data() {
   using namespace std;

   static int count = 1100000;

	while(1) {

                           bool die ;
                           mutex_.lock() ;
                           die = TIME_TO_DIE ;
                           mutex_.unlock() ;

                           if( die )
                           {
                                 return ;
                            }

		string line;
		string str01, str02;
		unsigned long value_mem_total = 0, value_mem_free = 0, value_mem_used = 0;
		unsigned long value_swap_total = 0, value_swap_free = 0;
		ifstream inFile(filename);

		if (inFile) {
			while (!inFile.eof()) {
				getline(inFile, line);
				istringstream inStr(line);
				inStr >> str01;
				if (str01.compare("Total") == 0) {
				  inStr >> str02 >> value_mem_total;
				} else if (str01.compare("Used") == 0) {
				  inStr >> str02 >> value_mem_used;
				} else if (str01.compare("SwapTotal:") == 0) {
				  inStr >> value_swap_total;
				} else if (str01.compare("SwapFree:") == 0) {
					inStr >> value_swap_free;
				}
			}
			inFile.close();
		} else {

		}

		std::string outBuffer;
		std::ostringstream outStr(outBuffer);

		std::string text;
		//value_mem_total
		outStr << value_mem_total << "KB";
		label_mem_total->set_text(outStr.str());
		//value_mem_free
		value_mem_free = value_mem_total - value_mem_used;
		outStr.str("");
		outStr << value_mem_free << "KB";
		label_mem_free->set_text(outStr.str());
		//value_mem_used
		outStr.str("");
		//used_mem_percentage
		int used_mem_percentage = (int)((double)value_mem_used/value_mem_total * 100);
		outStr << used_mem_percentage << "%";
		label_mem_used->set_text(outStr.str());

		//value_swap_total
		outStr.str("");
		outStr << value_swap_total << "KB";
		label_swap_total->set_text(outStr.str());
		//value_swap_free
		outStr.str("");
		outStr << value_swap_free << "KB";
		label_swap_free->set_text(outStr.str());
		//used_swap_percentage
		int value_swap_used = value_swap_total - value_swap_free;
	int used_swap_percentage = (int)((double)value_swap_used/value_swap_total * 100);

		//add new data into the plot array
		mutex_.lock();
		if (finished_drawing == false) {
			cond_drawing_.wait(mutex_);
		}
		plot_mem->add_new_data(used_mem_percentage);
		plot_swap->add_new_data(used_swap_percentage);
		finished_drawing = false;
		finished_adding_new_data = true;
		mutex_.unlock();
		count++;
	}

}


bool FrameNode::update_plot() {


	if (finished_adding_new_data == true) {
		plot_mem->plot_graph();
		plot_swap->plot_graph();
		finished_drawing = true;
		finished_adding_new_data = false;
		cond_drawing_.signal();
	}

	return true;
}


FrameNode::~FrameNode() {

}
------------------------------------------------------------------------



#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <gtkmm.h>
#include "FrameNode.h"
#include <fstream>

class MainWindow : public Gtk::Window {

public:
      MainWindow(char *);
      ~MainWindow();
      FrameNode *node;
protected:
       Gtk::VBox vbox_top;
		Gtk::HBox hbox_top;


};

#endif
------------------------------------------------------------------------



#include "MainWindow.h"
#include <iostream>

MainWindow::MainWindow(char *fname) :
   vbox_top(false, 0),
   hbox_top(false, 0)
{
   node = Gtk::manage(new FrameNode(fname));
   hbox_top.pack_start(*node, Gtk::PACK_SHRINK);
	vbox_top.pack_start(hbox_top, Gtk::PACK_SHRINK);
   add(vbox_top);

//	Glib::Thread *const read = Glib::Thread::create(sigc::mem_fun(node, &FrameNode::read_new_data), false);
Glib::Thread *const read = Glib::Thread::create(sigc::mem_fun(node, &FrameNode::read_new_data), true );

Delete this:

	try {
	  Glib::Thread *const read = Glib::Thread::create(sigc::mem_fun(node, &FrameNode::read_new_data), false);
	} catch(Glib::Thread::Exit&) {
	  // Just exit from the thread.  The Thread::Exit exception
	  // is our sane C++ replacement of g_thread_exit().
	} catch(...) {
	  Glib::exception_handlers_invoke();
	}

to here.

   show_all_children();

}


MainWindow::~MainWindow() {

   node->mutex_.lock() ;
   node->TIME_TO_DIE = true ;
   node->mutex_.unlock() ;

   read->join() ;

}



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