<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>cnfist 的个人博客</title>
	<atom:link href="http://cnfist.blogcn.com/feed" rel="self" type="application/rss+xml" />
	<link>http://cnfist.blogcn.com</link>
	<description>又一个 WordPress 站点</description>
	<lastBuildDate>Thu, 05 Apr 2012 05:47:58 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>消息代理结构</title>
		<link>http://cnfist.blogcn.com/articles/%e6%b6%88%e6%81%af%e4%bb%a3%e7%90%86%e7%bb%93%e6%9e%84.html</link>
		<comments>http://cnfist.blogcn.com/articles/%e6%b6%88%e6%81%af%e4%bb%a3%e7%90%86%e7%bb%93%e6%9e%84.html#comments</comments>
		<pubDate>Thu, 05 Apr 2012 05:47:58 +0000</pubDate>
		<dc:creator>cnfist</dc:creator>
				<category><![CDATA[old things]]></category>

		<guid isPermaLink="false">http://cnfist.blogcn.com/?p=99</guid>
		<description><![CDATA[]]></description>
			<content:encoded><![CDATA[<p><a href="http://files.blogcn.com/wp06/M00/02/7A/wKgKDU99MeEAAAAAAAB0XAkegGI092.png"><img src="http://files.blogcn.com/wp06/M00/02/7A/wKgKDU99MeEAAAAAAAB0XAkegGI092.png" alt="" title="消息代理结构图" width="677" height="730" class="aligncenter size-full wp-image-100"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://cnfist.blogcn.com/articles/%e6%b6%88%e6%81%af%e4%bb%a3%e7%90%86%e7%bb%93%e6%9e%84.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Test Driven Development</title>
		<link>http://cnfist.blogcn.com/articles/test-driven-development.html</link>
		<comments>http://cnfist.blogcn.com/articles/test-driven-development.html#comments</comments>
		<pubDate>Thu, 05 Apr 2012 05:44:03 +0000</pubDate>
		<dc:creator>cnfist</dc:creator>
				<category><![CDATA[项目管理]]></category>

		<guid isPermaLink="false">http://cnfist.blogcn.com/?p=94</guid>
		<description><![CDATA[软件测试驱动开发（TDD）是以测试作为开发过程的中心，它坚持，在编写实际代码之前，先写好基于产品代码的测试代码。开发过程的目标就是首先使测试能够通过，然后再优化设计结构。测试驱动开发式是极限编程的重要组成部分。 Test Driven Development Tutorial View more presentations from Kirrily Robert]]></description>
			<content:encoded><![CDATA[<p>软件测试驱动开发（TDD）是以测试作为开发过程的中心，它坚持，在编写实际代码之前，先写好基于产品代码的测试代码。开发过程的目标就是首先使测试能够通过，然后再优化设计结构。测试驱动开发式是极限编程的重要组成部分。</p>
<div style="width:425px" id="__ss_181371"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/Skud/test-driven-development-tutorial" title="Test Driven Development Tutorial" target="_blank">Test Driven Development Tutorial</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/181371" width="425" height="355" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/" target="_blank">presentations</a> from <a href="http://www.slideshare.net/Skud" target="_blank">Kirrily Robert</a></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://cnfist.blogcn.com/articles/test-driven-development.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Message Bus and Publish/Subscribe Pattern</title>
		<link>http://cnfist.blogcn.com/articles/message-bus-and-publishsubscribe-pattern.html</link>
		<comments>http://cnfist.blogcn.com/articles/message-bus-and-publishsubscribe-pattern.html#comments</comments>
		<pubDate>Wed, 28 Mar 2012 09:40:14 +0000</pubDate>
		<dc:creator>cnfist</dc:creator>
				<category><![CDATA[old things]]></category>

		<guid isPermaLink="false">http://cnfist.blogcn.com/?p=95</guid>
		<description><![CDATA[message bus 此文从集群系统模块之间的耦合性和系统的扩展性方面探讨了消息总线的优势与可行性。 消息总线的作用： 提供消息格式； 将消息发送到总线上的应用； 结合消息订阅发布模式，探讨了消息总线的大致方案。订阅发布模式可参考Publish/Subscribe。 其中尤其对订阅发布模式中的List-Based、Broadcast-Based、Content-Based三种方案进行了简单讲解。 参考此图。 文章提及了消息的识别与接受者匹配的方法，可参考BizTalk Server。]]></description>
			<content:encoded><![CDATA[<p><a href="http://msdn.microsoft.com/zh-cn/library/ms978583.aspx">message bus</a><br>
此文从集群系统模块之间的耦合性和系统的扩展性方面探讨了消息总线的优势与可行性。<br>
消息总线的作用：<br>
提供消息格式；<br>
将消息发送到总线上的应用；</p>
<p>结合消息订阅发布模式，探讨了消息总线的大致方案。订阅发布模式可参考<a href="http://msdn.microsoft.com/zh-cn/library/ff649664.aspx">Publish/Subscribe</a>。<br>
其中尤其对订阅发布模式中的List-Based、Broadcast-Based、Content-Based三种方案进行了简单讲解。<br>
参考此图<img src="http://i.msdn.microsoft.com/dynimg/IC97398.gif" alt="三种订阅发布方案">。<br>
文章提及了消息的识别与接受者匹配的方法，可参考<a href="http://msdn.microsoft.com/zh-CN/library/gg477078(v=bts.10).aspx">BizTalk Server</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://cnfist.blogcn.com/articles/message-bus-and-publishsubscribe-pattern.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Distributed System-remote procedure call</title>
		<link>http://cnfist.blogcn.com/articles/distributed-system-remote-procedure-call.html</link>
		<comments>http://cnfist.blogcn.com/articles/distributed-system-remote-procedure-call.html#comments</comments>
		<pubDate>Wed, 29 Jun 2011 09:52:17 +0000</pubDate>
		<dc:creator>cnfist</dc:creator>
				<category><![CDATA[old things]]></category>

		<guid isPermaLink="false">http://cnfist.blogcn.com/?p=93</guid>
		<description><![CDATA[What's local procedure call? A program invoke a local procedure call, pass it parameters and get the return data. See example: ret_type func(para_type arg); int main(int argc, char* argv[]){ ... ret_type ret=func((para_type)xxx); ... } What's remote procedure call? In an &#8230; <a href="http://cnfist.blogcn.com/articles/distributed-system-remote-procedure-call.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>What's local procedure call?</strong><br>
A program invoke a local procedure call, pass it parameters and get the return data. See example:<br>
ret_type func(para_type arg);<br>
int main(int argc, char* argv[]){<br>
...<br>
ret_type ret=func((para_type)xxx);<br>
...<br>
}</p>
<p><strong>What's remote procedure call?</strong><br>
In an client/server system, an client could run an procedure on server machine by sending request and attendant parameters to server, and get the result returned from procedure operating result.</p>
]]></content:encoded>
			<wfw:commentRss>http://cnfist.blogcn.com/articles/distributed-system-remote-procedure-call.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>重写operator new&amp;delete</title>
		<link>http://cnfist.blogcn.com/articles/%e9%87%8d%e5%86%99operator-newdelete.html</link>
		<comments>http://cnfist.blogcn.com/articles/%e9%87%8d%e5%86%99operator-newdelete.html#comments</comments>
		<pubDate>Wed, 29 Jun 2011 03:33:23 +0000</pubDate>
		<dc:creator>cnfist</dc:creator>
				<category><![CDATA[C++技术]]></category>

		<guid isPermaLink="false">http://cnfist.blogcn.com/?p=91</guid>
		<description><![CDATA[重写new关键字需要注意： void * operator new(size_t size); 1&#62; c++标准要求，即使在请求分配0字节内存时，operator new也要返回一个合法指针。比如分配一个1字节大小的内存。 2&#62; operator new内部包含一个无限循环，跳出循环的唯一办法是内存分配成功或出错处理函数完成了条款7所描述的事件中的一种：得到了更多的可用内存、安装了一个新的new-handler(出错处理函数)、卸除了mem_out_handler、抛出了一个std::bad_alloc或其派生类型的异常、或者返回失败。 3&#62; operator new经常会被子类继承，由于存在继承，基类中的operator new可能会被调用去为一个子类对象分配内存。从new函数的原型---------可知，调用父类的new函数时，传入的size比父类的sizeof大，因此简单的做法是分配此“错误”的size内存（: perator new(size)）。 重写delete函数需要注意： void operator delete(void *rawmemory, size_t size); 1&#62; C++标准要求，允许rawmemory为空指针。 2&#62; 子类继承时，delete子类时，基类中的operator delete传入的size参数可能和父类的sizeof不一致，此时也应该delete子类的内存空间(: perator delete(size))。]]></description>
			<content:encoded><![CDATA[<p>重写new关键字需要注意：<br>
void * operator new(size_t size);<br>
1&gt; c++标准要求，即使在请求分配0字节内存时，operator new也要返回一个合法指针。比如分配一个1字节大小的内存。<br>
2&gt; operator new内部包含一个无限循环，跳出循环的唯一办法是内存分配成功或出错处理函数完成了条款7所描述的事件中的一种：得到了更多的可用内存、安装了一个新的new-handler(出错处理函数)、卸除了mem_out_handler、抛出了一个std::bad_alloc或其派生类型的异常、或者返回失败。<br>
3&gt; operator new经常会被子类继承，由于存在继承，基类中的operator new可能会被调用去为一个子类对象分配内存。从new函数的原型---------可知，调用父类的new函数时，传入的size比父类的sizeof大，因此简单的做法是分配此“错误”的size内存（: <img src='http://cnfist.blogcn.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley'> perator new(size)）。</p>
<p>重写delete函数需要注意：<br>
void operator delete(void *rawmemory, size_t size);<br>
1&gt; C++标准要求，允许rawmemory为空指针。<br>
2&gt; 子类继承时，delete子类时，基类中的operator delete传入的size参数可能和父类的sizeof不一致，此时也应该delete子类的内存空间(: <img src='http://cnfist.blogcn.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley'> perator delete(size))。</p>
]]></content:encoded>
			<wfw:commentRss>http://cnfist.blogcn.com/articles/%e9%87%8d%e5%86%99operator-newdelete.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>处理new操作内存不足</title>
		<link>http://cnfist.blogcn.com/articles/%e5%a4%84%e7%90%86new%e6%93%8d%e4%bd%9c%e5%86%85%e5%ad%98%e4%b8%8d%e8%b6%b3.html</link>
		<comments>http://cnfist.blogcn.com/articles/%e5%a4%84%e7%90%86new%e6%93%8d%e4%bd%9c%e5%86%85%e5%ad%98%e4%b8%8d%e8%b6%b3.html#comments</comments>
		<pubDate>Wed, 29 Jun 2011 02:44:14 +0000</pubDate>
		<dc:creator>cnfist</dc:creator>
				<category><![CDATA[C++技术]]></category>

		<guid isPermaLink="false">http://cnfist.blogcn.com/?p=89</guid>
		<description><![CDATA[********************************************************************************* 简单的方法 类定义 typedef void (*mem_out_handler)(); class x { public: static mem_out_handler set_handler(mem_out_handler p); static void * operator new(size_t size); private: static mem_out_handler currenthandler; }; mem_out_handler x::set_handler(mem_out_handler p) { mem_out_handler oldhandler = currenthandler; currenthandler = p; return oldhandler; } void &#8230; <a href="http://cnfist.blogcn.com/articles/%e5%a4%84%e7%90%86new%e6%93%8d%e4%bd%9c%e5%86%85%e5%ad%98%e4%b8%8d%e8%b6%b3.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>*********************************************************************************<br>
<strong>简单的方法</strong><br>
类定义<br>
typedef void (*mem_out_handler)();</p>
<p>class x {<br>
public:<br>
static mem_out_handler set_handler(mem_out_handler p);<br>
static void * operator new(size_t size);</p>
<p>private:<br>
static mem_out_handler currenthandler;<br>
};</p>
<p>mem_out_handler x::set_handler(mem_out_handler p)<br>
{<br>
mem_out_handler oldhandler = currenthandler;<br>
currenthandler = p;<br>
return oldhandler;<br>
}<br>
void * x: <img src='http://cnfist.blogcn.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley'> perator new(size_t size)<br>
{<br>
mem_out_handler globalhandler = std::set_new_handler(currenthandler);// 安装x的new_handler<br>
void *memory;<br>
try { // 尝试分配内存<br>
memory = : <img src='http://cnfist.blogcn.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley'> perator new(size);<br>
}<br>
catch (std::bad_alloc&amp; <img src='http://cnfist.blogcn.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley'> { // 恢复旧的new_handler<br>
std::set_new_handler(globalhandler);<br>
throw; // 抛出异常<br>
}<br>
std::set_new_handler(globalhandler); // 恢复旧的new_handler<br>
return memory;<br>
}<br>
mem_out_handler x:currenthandler=NULL;</p>
<p>内存分配<br>
static void nomorememory();// x的对象分配内存失败时调用的new_handler函数的声明</p>
<p>x::set_handler(nomorememory);// 把nomorememory设置为x的mem_out_handler函数<br>
x *px1 = new x; // 如内存分配失败，调用nomorememory<br>
x::set_handler(0); // 设x的mem_out_handler函数为空<br>
x *px2 = new x; // 如内存分配失败，立即抛出异常。(类x当前没有mem_out_handler函数)</p>
<p>*********************************************************************************<br>
<strong>可重用方法</strong></p>
<p>定义<br>
template<br>
class base {<br>
public:<br>
static mem_out_handler set_handler(mem_out_handler p);<br>
static void * operator new(size_t size);</p>
<p>private:<br>
static mem_out_handler currenthandler;<br>
};</p>
<p>template<br>
mem_out_handler base::set_handler(mem_out_handler p)<br>
{<br>
mem_out_handler oldhandler = currenthandler;<br>
currenthandler = p;<br>
return oldhandler;<br>
}</p>
<p>template<br>
void * newhandlersupport: <img src='http://cnfist.blogcn.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley'> perator new(size_t size)<br>
{<br>
mem_out_handler globalhandler =<br>
std::set_new_handler(currenthandler);<br>
void *memory;<br>
try {<br>
memory = : <img src='http://cnfist.blogcn.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley'> perator new(size);<br>
}<br>
catch (std::bad_alloc&amp; <img src='http://cnfist.blogcn.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley'> {<br>
std::set_new_handler(globalhandler);<br>
throw;<br>
}</p>
<p>std::set_new_handler(globalhandler);<br>
return memory;<br>
}</p>
<p>template<br>
mem_out_handler base::currenthandler=NULL;</p>
<p>//inheritance from mixin base class template.<br>
class x: public base {<br>
... // as before, but no declarations for set_handler or operator new<br>
};</p>
]]></content:encoded>
			<wfw:commentRss>http://cnfist.blogcn.com/articles/%e5%a4%84%e7%90%86new%e6%93%8d%e4%bd%9c%e5%86%85%e5%ad%98%e4%b8%8d%e8%b6%b3.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>how to redirect output of an running process</title>
		<link>http://cnfist.blogcn.com/articles/how-to-redirect-output-of-an-running-process.html</link>
		<comments>http://cnfist.blogcn.com/articles/how-to-redirect-output-of-an-running-process.html#comments</comments>
		<pubDate>Thu, 16 Jun 2011 06:31:36 +0000</pubDate>
		<dc:creator>cnfist</dc:creator>
				<category><![CDATA[old things]]></category>

		<guid isPermaLink="false">http://cnfist.blogcn.com/?p=87</guid>
		<description><![CDATA[http://etbe.coker.com.au/2008/02/27/redirecting-output-from-a-running-process/ Note: redirecting output of an running process, not when starting a process, so '&#62;' is ignored. Take cat &#62; /home/fist/output for example, this command would accept input of prompt, and write user inputs to the file "/home/fist/output". What should &#8230; <a href="http://cnfist.blogcn.com/articles/how-to-redirect-output-of-an-running-process.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>http://etbe.coker.com.au/2008/02/27/redirecting-output-from-a-running-process/</p>
<p><em>Note: redirecting output of an running process, not when starting a process, so '&gt;' is ignored.</em><br>
Take <em><span style="color: #ff6600;">cat &gt; /home/fist/output</span></em> for example, this command would accept input of prompt, and write <em><span style="color: #99cc00;">user inputs</span></em> to the file "/home/fist/output".<br>
What should we do , if we want to redirect the output of the program to another file, /home/fist/direct.txt for instance?<br>
With the help of gdb, we can attach a running process, manipulating it's resources, passing messages, and invoking system calls in its' context.<br>
As we know, there are three standard file: <em><span style="color: #99cc00;">stdin, stdout</span></em> <span style="color: #99cc00;">and <em><span style="color: #99cc00;">stderr</span></em></span>, which are indexed by 0, 1 and 2 in a processes' context(0, 1, 2.etc are file descriptor). When we open a new file right after closing an existing one, the new file's descriptor would be just the same as the previous one. So, if we close <em>stdout</em>, and creat another one, the later one would use the file descriptor "1".<br>
But how to close an existing file, and open another one? Follow me!<br>
..............................................................................................<br>
$ pgrep watch<br>
3457<br>
$ which watch<br>
/usr/bin/watch<br>
$ gdb -p 3457 /usr/bin/watch<br>
...<br>
(gdb) p close(1)<br>
$1 = 0<br>
(gdb) p creat("/home/fist/redirect", 0644)<br>
$2 = 1<br>
(gdb) quit<br>
The program is running. Quit anyway(and detach it)?(y or n) y<br>
Detaching from program: /usr/bin/watch, process 3457<br>
..............................................................................................<br>
The “p” command in GDB will print the value of an expression, an expression can be a function to call, it can be a system call… So I execute a <span style="color: #339966;">close()</span> system call and pass file handle 1, then I execute a <span style="color: #339966;">creat()</span> system call to open a new file. The result of the <span style="color: #339966;">creat()</span> was 1 which means that it replaced the previous file handle. If I wanted to use the same file for stdout and stderr or if I wanted to replace a file handle with some other number then I would need to call the <span style="color: #339966;">dup2()</span> system call to achieve that result.<br>
To verify the result, we type some words into the session of cat, and <em>see</em> the content of&nbsp;<em><span style="color: #ff6600;">/home/fist/redirect</span></em>.You will see the difference.<br>
Also, if you want to close the original session you need to close all file handles for it, open a new device that can be the controlling tty, and then call <span style="color: #339966;">setsid()</span>.<br>
..............................................................................................<br>
[More]<br>
Above method can be used to debug a running program ,by redirecting stdin, stdout and stderr to another session.The program can be a dameon, a program with no GUI interface, a console, etc.<br>
Another advanced debugging method is signal. When programing, debug is planted in the program's gene.By sending,capturing and handling signal, more complicated debugging methods are supported.</p>
]]></content:encoded>
			<wfw:commentRss>http://cnfist.blogcn.com/articles/how-to-redirect-output-of-an-running-process.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Architecture of MessagePack</title>
		<link>http://cnfist.blogcn.com/articles/architecture-of-messagepack.html</link>
		<comments>http://cnfist.blogcn.com/articles/architecture-of-messagepack.html#comments</comments>
		<pubDate>Mon, 13 Jun 2011 01:11:10 +0000</pubDate>
		<dc:creator>cnfist</dc:creator>
				<category><![CDATA[进程通信]]></category>

		<guid isPermaLink="false">http://cnfist.blogcn.com/?p=85</guid>
		<description><![CDATA[OverView MessagePack offers two layered software components. 1.MessagePack is an efficient object serialization library.It enables to exchange structured objects between many languages like JSON. But unlike JSON, it is very fast and small. 2.MessagePack-RPC is the remote procedure call system &#8230; <a href="http://cnfist.blogcn.com/articles/architecture-of-messagepack.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<h3>OverView</h3>
<div style="width: 595px;"><strong>MessagePack</strong> offers two layered software components.</div>
<address><strong>1.MessagePack</strong> is an efficient object serialization library.It enables to exchange structured objects between many languages like JSON. But unlike JSON, it is very fast and small.</address>
<address>2.<strong>MessagePack-RP</strong>C is the remote procedure call system on top of the MessagePack serialization library.It is a cross-language RPC library for client, server and cluster applications, which releases you from complicated network programming completely and provides well-designed API.</address>
<div style="width:510px" id="__ss_4405131"><strong style="display:block;margin:12px 0 4px"><a href="http://www.slideshare.net/frsyuki/architecture-of-messagepack" title="Architecture of MessagePack">Architecture of MessagePack</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/4405131" width="510" height="426" frameborder="0" marginwidth="0" marginheight="0" scrolling="no"></iframe>
<div style="padding:5px 0 12px">View more <a href="http://www.slideshare.net/">presentations</a> from <a href="http://www.slideshare.net/frsyuki">frsyuki</a></div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://cnfist.blogcn.com/articles/architecture-of-messagepack.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Paxos算法</title>
		<link>http://cnfist.blogcn.com/articles/paxos%e7%ae%97%e6%b3%95.html</link>
		<comments>http://cnfist.blogcn.com/articles/paxos%e7%ae%97%e6%b3%95.html#comments</comments>
		<pubDate>Fri, 03 Jun 2011 09:08:12 +0000</pubDate>
		<dc:creator>cnfist</dc:creator>
				<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://cnfist.blogcn.com/?p=80</guid>
		<description><![CDATA[http://zh.wikipedia.org/wiki/Paxos%E7%AE%97%E6%B3%95 http://en.wikipedia.org/wiki/Paxos_(computer_science) Paxos 算法解决的问题是一个分布式系统如 何就某个值（决议）达成一致。一个典型的场景是，在一个分布式数据库系统中，如果各节点的初始状态一致，每个节点都执行相同的操作序列，那么他们最后能得 到一个一致的状态。为保证每个节点执行相同的命令序列，需要在每一条指令上执行一个“一致性算法”以保证每个节点看到的指令一致。这在节点可能无法连接的情况下变得更加困难。一个通用的一致性算法可 以应用在许多场景中，是分布式计算中的重要问题。因此从20世纪80年代起对于一致性算法的研究就没有停止过。节点通信存在两种模型：共享内存（Shared memory）和消息传递（Messages passing）。Paxos 算法就是一种基于消息传递模型的一致性算法。 场景定义： 将节点的角色分为 proposers，acceptors，和 learners（允许身兼数职）。proposers 提出决议，acceptors 批准决议，learners“学习”决议。 需求定义： 决议（value）只有在被 proposers 提出后才能批准（未经批准的决议称为“提案（proposal）”）； 在一次 Paxos 算法的执行实例中，只批准一个 Value； learners 只能获得被批准（chosen）的 Value。 算法的内容： proposer 提出一个提案前，首先要和足以形成多数派的 acceptors 进行通信，获得他们进行的最近一次批准活动的编号（prepare 过程），之后根据回收的信息决定这次提案的 value，形成提案开始投票。当获得多数 acceptors 批准后，提案获得通过，由 proposer 将这个消息告知 learner。这个简略的过程经过进一步细化后就形成了 Paxos &#8230; <a href="http://cnfist.blogcn.com/articles/paxos%e7%ae%97%e6%b3%95.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>http://zh.wikipedia.org/wiki/Paxos%E7%AE%97%E6%B3%95</p>
<p>http://en.wikipedia.org/wiki/Paxos_(computer_science)</p>
<p>Paxos 算法解决的问题是一个<a title="分布式系统" href="http://zh.wikipedia.org/w/index.php?title=%E5%88%86%E5%B8%83%E5%BC%8F%E7%B3%BB%E7%BB%9F&amp;action=edit&amp;redlink=1">分布式系统</a>如 何就某个值（决议）达成一致。一个典型的场景是，在一个分布式数据库系统中，如果各节点的初始状态一致，每个节点都执行相同的操作序列，那么他们最后能得 到一个一致的状态。为保证每个节点执行相同的命令序列，需要在每一条指令上执行一个“一致性算法”以保证每个节点看到的指令一致。这在节点可能无法连接的情况下变得更加困难。一个通用的一致性算法可 以应用在许多场景中，是分布式计算中的重要问题。因此从20世纪80年代起对于一致性算法的研究就没有停止过。节点通信存在两种模型：<a title="共享内存" href="http://zh.wikipedia.org/wiki/%E5%85%B1%E4%BA%AB%E5%86%85%E5%AD%98">共享内存</a>（Shared memory）和<a title="消息传递" href="http://zh.wikipedia.org/w/index.php?title=%E6%B6%88%E6%81%AF%E4%BC%A0%E9%80%92&amp;action=edit&amp;redlink=1">消息传递</a>（Messages passing）。Paxos 算法就是一种基于消息传递模型的一致性算法。</p>
<h3>场景定义：</h3>
<p>将节点的角色分为 proposers，acceptors，和 learners（允许身兼数职）。proposers 提出决议，acceptors 批准决议，learners“学习”决议。</p>
<h3>需求定义：</h3>
<ol>
<li>决议（value）只有在被 proposers 提出后才能批准（未经批准的决议称为“提案（proposal）”）；</li>
<li>在一次 Paxos 算法的执行实例中，只批准一个 Value；</li>
<li>learners 只能获得被批准（chosen）的 Value。</li>
</ol>
<h3>算法的内容：</h3>
<p>proposer 提出一个提案前，首先要和足以形成多数派的 acceptors 进行通信，获得他们进行的最近一次批准活动的编号（prepare 过程），之后根据回收的信息决定这次提案的 value，形成提案开始投票。当获得多数 acceptors 批准后，提案获得通过，由 proposer 将这个消息告知 learner。这个简略的过程经过进一步细化后就形成了 Paxos 算法。</p>
<h4>决议的提出与通过：</h4>
<p>通过一个决议分为两个阶段：</p>
<ol>
<li>prepare 阶段：
<ol>
<li>proposer 选择一个提案编号 n 并将 prepare 请求发送给 acceptors 中的一个多数派；</li>
<li>acceptor 收到 prepare 消息后，如果提案的编号大于它已经回复的所有 prepare 消息，则 acceptor 将自己上次的批准回复给 proposer，并承诺不再批准小于 n 的提案；</li>
</ol>
</li>
<li>批准阶段：
<ol>
<li>当一个 proposor 收到了多数 acceptors 对 prepare 的回复后，就进入批准阶段。它要向回复 prepare 请求的 acceptors 发送 accept 请求，包括编号 n 和根据 P2c 决定的 value（如果根据 P2c 没有决定 value，那么它可以自由决定 value）。</li>
<li>在不违背自己向其他 proposer 的承诺的前提下，acceptor 收到 accept 请求后即批准这个请求。</li>
</ol>
</li>
</ol>
<h4>决议的发布：</h4>
<p>一个显而易见的方法是当 acceptors 批准一个 value 时，将这个消息发送给所有 learner。但是这个方法会导致消息量过大。<br>
由于假设没有 Byzantine failures，learners 可以通过别的 learners 获取已经通过的决议。因此 acceptors 只需将批准的消息发送给指定的某一个 learner，其他 learners 向它询问已经通过的决议。这个方法降低了消息量，但是指定 learner 失效将引起系统失效。<br>
因此 acceptors 需要将 accept 消息发送给 learners 的一个子集，然后由这些 learners 去通知所有 learners。<br>
但是由于消息传递的不确定性，可能会没有任何 learner 获得了决议批准的消息。当 learners 需要了解决议通过情况时，可以让一个 proposer 重新进行一次提案。注意一个 learner 可能兼任 proposer。</p>
<h4>Progress 的保证：</h4>
<p>根据上述过程当一个 proposer 发现存在编号更大的提案时将终止提案。这意味这提出一个编号更大的提案会终止之前的提案过程。如果两个 proposer 在这种情况下都转而提出一个编号更大的提案，就可能陷入活锁，违背了 Progress 的要求。这种情况下的解决方案是选举出一个 president，仅允许 president 提出提案。但是由于消息传递的不确定性，可能有多个 proposer 自认为自己已经成为 president。Lamport 在<a rel="nofollow" href="http://research.microsoft.com/users/lamport/pubs/lamport-paxos.pdf">The Part-Time Parliament</a>一文中描述并解决了这个问题。</p>
]]></content:encoded>
			<wfw:commentRss>http://cnfist.blogcn.com/articles/paxos%e7%ae%97%e6%b3%95.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>qt事件处理和事件过滤</title>
		<link>http://cnfist.blogcn.com/articles/qt%e4%ba%8b%e4%bb%b6%e5%a4%84%e7%90%86%e5%92%8c%e4%ba%8b%e4%bb%b6%e8%bf%87%e6%bb%a4.html</link>
		<comments>http://cnfist.blogcn.com/articles/qt%e4%ba%8b%e4%bb%b6%e5%a4%84%e7%90%86%e5%92%8c%e4%ba%8b%e4%bb%b6%e8%bf%87%e6%bb%a4.html#comments</comments>
		<pubDate>Tue, 31 May 2011 03:40:25 +0000</pubDate>
		<dc:creator>cnfist</dc:creator>
				<category><![CDATA[C++技术]]></category>

		<guid isPermaLink="false">http://cnfist.blogcn.com/?p=77</guid>
		<description><![CDATA[1.事件驱动模式 在事件驱动的程序中，GUI视图需要响应object的状态变化，作出特定反应。当状态变化时，将对应的信息发送给接收者。 事件的来源有两类，一种是系统事件，例如鼠标键盘事件，qt获取到这些来自系统底层的消息，将它们转换成qt的事件，放入事件队列；另一种是应用程序事件，例如postEvent/sendEvent。 事件通过各种各样的方式在object间传递。QWidget通过QEvent发送给其他QObject，以相应鼠标或键盘操作；QObject之间可通过signal/slot机制进行事件处理。 2.事件处理流程 3.event loop 下面是一个典型的qt主程序示例： int main(int argc, char * argv[]) { QApplication myapp(argc, argv); QWidget rootWidget; setGui(&#38;rootWidget); rootWidget.show(); return myapp.exec(); }; Every GUI, multithreaded, or event-driven Qt Application must have a QApplication object defined at the &#8230; <a href="http://cnfist.blogcn.com/articles/qt%e4%ba%8b%e4%bb%b6%e5%a4%84%e7%90%86%e5%92%8c%e4%ba%8b%e4%bb%b6%e8%bf%87%e6%bb%a4.html">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>1.事件驱动模式</p>
<p>在事件驱动的程序中，GUI视图需要响应object的状态变化，作出特定反应。当状态变化时，将对应的信息发送给接收者。<br>
事件的来源有两类，一种是系统事件，例如鼠标键盘事件，qt获取到这些来自系统底层的消息，将它们转换成qt的事件，放入事件队列；另一种是应用程序事件，例如postEvent/sendEvent。<br>
事件通过各种各样的方式在object间传递。QWidget通过QEvent发送给其他QObject，以相应鼠标或键盘操作；QObject之间可通过signal/slot机制进行事件处理。</p>
<p>2.事件处理流程<br>
<a href="http://files.blogcn.com/wp05/M00/00/AC/wKgKDE3kYgEAAAAAAAAZnniynfo306.gif"><img class="aligncenter size-medium wp-image-78" title="qt事件处理流程" src="http://files.blogcn.com/wp02/M00/00/E9/wKgKCk3kYgIAAAAAAAAtJg8_CFA856.gif" alt="" width="397" height="340"></a><br>
<img src="file:///tmp/moz-screenshot.jpg" alt=""><img src="file:///tmp/moz-screenshot-1.jpg" alt=""></p>
<p>3.event loop</p>
<p>下面是一个典型的qt主程序示例：<br>
int main(int argc, char * argv[]) {<br>
<a href="http://cartan.cas.suffolk.edu/qtdocs/qapplication.html"><tt>QApplication</tt></a> myapp(argc, argv); <a name="co0-1304023512.11163" id="co0-1304023512.11163"></a><img src="http://cartan.cas.suffolk.edu/oopdocbook/opensource/icons/callouts/1.png" border="0" alt="1"><a href="http://cartan.cas.suffolk.edu/qtdocs/qwidget.html"><tt><br>
QWidget</tt></a> rootWidget;<br>
setGui(&amp;rootWidget);<br>
rootWidget.show(); <a name="co1-1304023512.11197" id="co1-1304023512.11197"></a><img src="http://cartan.cas.suffolk.edu/oopdocbook/opensource/icons/callouts/2.png" border="0" alt="2"><br>
return myapp.exec(); <a name="co2-1304023512.11209" id="co2-1304023512.11209"></a><img src="http://cartan.cas.suffolk.edu/oopdocbook/opensource/icons/callouts/3.png" border="0" alt="3"><br>
};</p>
<div>
<table style="height: 131px;" border="0" width="625" summary="Callout list">
<tbody>
<tr>
<td width="5%" align="left" valign="top"><a href="http://cartan.cas.suffolk.edu/oopdocbook/opensource/eventloop.html#co0-1304023512.11163"><img src="http://cartan.cas.suffolk.edu/oopdocbook/opensource/icons/callouts/1.png" border="0" alt="1"></a></td>
<td align="left" valign="top">Every GUI, multithreaded, or event-driven Qt Application must have a <a href="http://cartan.cas.suffolk.edu/qtdocs/qapplication.html"><tt>QApplication</tt></a> object defined at the top of main().</td>
</tr>
<tr>
<td width="5%" align="left" valign="top"><a href="http://cartan.cas.suffolk.edu/oopdocbook/opensource/eventloop.html#co1-1304023512.11197"><img src="http://cartan.cas.suffolk.edu/oopdocbook/opensource/icons/callouts/2.png" border="0" alt="2"></a></td>
<td align="left" valign="top">Show the widget on the screen.</td>
</tr>
<tr>
<td width="5%" align="left" valign="top"><a href="http://cartan.cas.suffolk.edu/oopdocbook/opensource/eventloop.html#co2-1304023512.11209"><img src="http://cartan.cas.suffolk.edu/oopdocbook/opensource/icons/callouts/3.png" border="0" alt="3"></a></td>
<td align="left" valign="top">Enter an event loop.</td>
</tr>
</tbody>
</table>
</div>
<p>当调用QApplication::exec()函数之后，程序就进入了event loop，接收、处理、分发各种事件，直到程序退出。QApplication::exec()的简化逻辑如下所示：<br>
while ( !app_exit_loop ) {<br>
while( !postedEvents ) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; processPostedEvents()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
while( !qwsEvnts ){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; qwsProcessEvents();&nbsp;&nbsp; }<br>
while( !postedEvents ) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; processPostedEvents()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>
}</p>
<p>4.事件处理和事件过滤方法</p>
<p>1）QEvent子类<br>
qt4.*中继承自QEvent的子类有QTimerEvent, QMouseEvent, QWheelEvent, QTabletEvent, QKeyEvent, QFocusEvent, QPaintEvent, QMoveEvent, QResizeEvent, QCloseEvent, QIconDragEvent, QShowEvent, QHideEvent, QContextMenuEvent, QIMEvent, QDropEvent, QDragLeaveEvent, QChildEvent, QCustomEvent.<br>
开发者可以通过重载QWidget和QObject提供的事件处理方法，来响应对应的事件。例如，重载QWidget::mousePressEvent ( QMouseEvent * e )之后，我们就可以自行处理窗体的鼠标点击事件。</p>
<p>2）QObject::event()<br>
通过重载event()，可以在某些事件到达本实例的特定事件处理器之前处理他们。对于那些没有明确需要预先处理的事件，需要调用其基类的event()函数。</p>
<p>3）QObject event filter<br>
QObject::installEventFilter ( const QObject * filterObj )方法将filterObj注册为本对象的事件监视对象，即所有本对象的事件都会发送到filterObj。filterObj在QObject::eventFilter(QObject *o, QEvent *e )方法中截获并过滤所有事件，重载此方法，在其中过滤特定的事件。在对特定事件进行过滤之后，eventFilter需要返回TRUE，若不需要过滤或者要将过滤后的事件继续传递下去，则返回FALSE，此时要保证不要delete掉事件e。<br>
一个监视器可以监视多个QObject，一个QObject可以被多个监视器监视，如果QObject被多个监视器监视，则消息按照监视器被注册的顺序传递到各个监视器。</p>
<p>4）QApplication::notify()<br>
Qt调用QApplication::notify( QObject * receiver, QEvent * e )方法将事件e发送到receiver。</p>
<p>5）注册QApplication的监视器<br>
所有事件在被处理和过滤之前，将被此监视器过滤。</p>
]]></content:encoded>
			<wfw:commentRss>http://cnfist.blogcn.com/articles/qt%e4%ba%8b%e4%bb%b6%e5%a4%84%e7%90%86%e5%92%8c%e4%ba%8b%e4%bb%b6%e8%bf%87%e6%bb%a4.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

