Re: How to properly exit a thread?
- From: Paul Davis <pjdavis engineering uiowa edu>
 
- To: Xiangfei Jia <xjianz gmail com>
 
- Cc: gtkmm-list gnome org
 
- Subject: Re: How to properly exit a thread?
 
- Date: Sun, 14 May 2006 15:35:35 -0500
 
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]