??xml version="1.0" encoding="utf-8" standalone="yes"?> 首先下蝲源码?br /> http://www.cmake.org/cmake/resources/software.html q里下蝲的是cmake-2.8.9.tar.gz 随便找个目录解压~?/p>
依次执行Q?/p>
cmake ?x)默认安装?/usr/local/bin 下面 要改变安装\径,在bootstrap命o(h)中加?--prefix=PATH'选项? #yum install gcc gcc-c++ bzip2 bzip2-devel bzip2-libs python-devel -y #tar xvzf boost_1_50_0.tar.gz #cd boost_1_50_0 然后是编译安装,boost源码包中有配|脚本,直接用就可以Q?/p> #sh ./bootstrap.sh Building Boost.Build engine with toolset gcc... tools/build/v2/engine/bin.linuxx86_64/b2 #./b2 The Boost C++ Libraries were successfully built! #./b2 install --prefix=/usr/local 下面是html代码部分Q?/p>
对应的jQuery代码如下Q?/p>
当点击spanӞ?x)触发div与body 的点M件。点击div时会(x)触发body的点M件?/p>
如何防止q种冒事g发生呢? 修改如下Q?/p>
event.stopPropagation(); // L事g冒 有时候点?yn)L交按钮会(x)有一些默认事件。比如蟩转到别的界面。但是如果没有通过验证的话Q就不应该蟩转。这时候可以通过讄event.preventDefault(); //L默认行ؓ(f) ( 表单提交 )?/p>
下面是案例:(x) html部分Q?/p>
q有一U防止默认行为的Ҏ(gu)是return false。效果一栗?/p>
代码如下Q?/p>
同理Q上面的冒事g也可以通过return false来处理?/p>
1.1 Wait-freedom 无等待ƈ?/p>
Wait-freedom 指的是每一个线E都一直运行下去而无ȝ待外部条Ӟ整个程中Q何操作都能在一个有限的步骤内完成,q是最高的q发U别Q没有Q何阻塞?/p>
l合之前原子操作部分的知识,可以单认够直接调用一个原子操作实现的法或程序就属于Wait-freeQ比如下面的 increment_reference_counter 函数是wait-free的,它封装了atomic_incrementq个原子自增原语Q多个线E可以同时调用这个函数对同一个内存变量进行自增,而无MQ何阻塞(其实也是有阻塞的Q是ȝ锁别) 与此做对比,CAScȝ调用׃是wait-free的,注意wait-free的原语都不能包含内部循环QCAS原语使用旉常包含?#8220;循环直到成功”的@环内部?/p>
void increment_reference_counter(rc_base* obj) { atomic_increment(obj->rc); } 1.2 Lock-freedom 无锁q发 Lock-freedom 指的是整个系l作Z个整体一直运行下去,pȝ内部单个U程某段旉内可能会(x)饥饿Q这是比wait-freedomqq发U别Q但pȝ整体上看依然是没有阻塞的。所有wait-free的算法显焉满lock-free的要求?/p>
Lock-free法通常可以通过同步原语 CAS实现?/p>
void stack_push(stack* s, node* n) { node* head; do { head = s->head; n->next = head; } while ( ! atomic_compare_exchange(s->head, head, n)); } 多个U程同时调用上述函数Q理Z某个U程可以一直困在@环内部,但一旦有一个线E原子操作失败而返回@环,意味着有其他线E成功执行了原子操作而退出@环,从而保证系l整体是没有d的?/p>
其实前面的原子自增函C可以用下面的原语实现Q在q种实现里,不再是所有线E都无阻塞了Q某些线E可能会(x)因ؓ(f)CASp|而回l若q次循环?/p>
void increment_reference_counter(rc_base* obj) { Int rc; Do { rc = obj->rc; } while(!atomic_compare_exchange(obj->rc,rc,rc+1)); } 1.3 Obstruction-freedom 无阻塞ƈ?/p>
Obstruction-free 是指在Q何时间点Q一个孤立运行线E的每一个操作可以在有限步之内结束。只要没有竞争,U程可以持l运行,一旦共享数据被修改QObstruction-free 要求中止已经完成的部分操作,q进行回滚,obstruction-free 是ƈ发别更低的非阻塞ƈ发,该算法在不出现冲H性操作的情况下提供单U程式的执行q度保证Q所?Lock-Free 的算法都?Obstruction-free 的?/p>
1.4 Blocking algoithms dq发 dcȝ法是ƈ发别最低的同步法Q它一般需要生阻塞。可以简单认为基于锁的实现是blocking的算法。详l参考第五章 上述几种q发U别可以使用下图描述Q?br />蓝色是阻塞的法Q绿色是非阻塞算法,金字塔越上方Qƈ发别越高,性能好Q右边的金字塔是实现工具Q原子操作、锁、互斥体{) 以前一直不明白lock free是什么,后来发现原来是完全理解错了概念,lock free看到大家有的译为无锁,有的译为锁无关Q其实用不用锁和lock free是不相关的,用了锁也可能是lock freeQ而不用锁有可能不是lock free?br /> 一个lock free的解释是 一?#8220;锁无?#8221;的程序能够确保执行它的所有线E中臛_有一个能够l往下执行? 其实看我们那副图是说你的各个线E不?x)互盔R塞,那么你的E序才能成ؓ(f)lock free的。像我们q_用的互斥锁,当有U程获得锁,其他U程pd掉了Q这里的问题是如果获得锁的U程挂掉了,而且锁也没有释放Q那么整个程序其实就被block在那了,而如果程序是lock free的那么即使有U程挂掉Q也不媄响整个程序l向下进行,也就是系l在整体上而言是一直前q的?/p>
那么Q不用锁是lock free的吗Q一开始就提到了,不用锁也可能不是lock free的,举个例子 在这里如果两个线E同时执行,可能同时q入while循环Q然后x两次改变g后,依然?Q那么两个线E就?x)一直互相在q里d掉了Q所以这里虽然没有锁Q依然不是lock free的?/p>
现在大家写lock free的时候一般都?x)用CASQcompare and setQ操作来写,因ؓ(f)现在很多的cpu都是支持CAS操作q作为原子操作来处理的,CAS操作一般是q样?/p>
其实q样一个操作和乐观锁很像,q且操作单,相应的比互斥锁的代h(hun)要小。所以现在大安是喜Ƣ用lock free的技术来提高pȝ的performance?/p>
最后如果大家对于如何编写lock free的数据结构感兴趣的话Q可以参考我后面l出的链接?/p>
一U高效无锁内存队列的实现
]]>
]]>
1
tar
-xzvf cmake-2.8.9.
tar
.gz
2
cd
cmake-cmake-2.8.9
1
./bootstrap
2
make
3
make
install
二?/span>linux下安装boost
linuxq_下要~译安装除gcc和gcc-c++之外Q还需要两个开发库Qbzip2-devel 和python-develQ因此在安装前应该先保证q两个库已经安装Q?br />
然后是去官网下蝲源码包,地址
下蝲Q解压,按照如下步骤Q?br />
q入boost_1_50_0目录Q?br />
接下来就是编译,重点x是否~译成功Q?br />
Detecting Python version... 2.6
Detecting Python root... /usr
Unicode/ICU support for Boost.Regex?... not found.
Generating Boost.Build configuration in project-config.jam...
Bootstrapping is done. To build, run:
./b2
To adjust configuration, edit 'project-config.jam'.
Further information:
- Command line help:
./b2 --help
- Getting started guide:
http://www.boost.org/more/getting_started/unix-variants.html
- Boost.Build documentation:
http://www.boost.org/boost-build2/doc/html/index.html
然后是漫长的等待,如果最后出玎ͼ(x)
表示~译成功Q如果没有成功,需要回查看哪里出现errorQ再安装相应的库Q?br />最后就是安装:(x)
The following directory should be added to compiler include paths:
/home/gang/BAK/boost_1_50_0
The following directory should be added to linker library paths:
/home/gang/BAK/boost_1_50_0/stage/lib
安装后的头文件在/usr/local/include/boost里面Q而相应的库在/usr/local/lib/libboost_*
]]>
冒事g是点击子节点,?x)向上触发父节点Q祖先节点的点击事g?/p>
<body>
<div id="content">
外层div元素
<span>内层span元素</span>
外层div元素
</div>
<div id="msg"></div>
</body>
<script type="text/javascript">
$(function(){
// 为span元素l定click事g
$('span').bind("click",function(){
var txt = $('#msg').html() + "<p>内层span元素被点?<p/>";//获取html信息
$('#msg').html(txt);// 讄html信息
});
// 为div元素l定click事g
$('#content').bind("click",function(){
var txt = $('#msg').html() + "<p>外层div元素被点?<p/>";
$('#msg').html(txt);
});
// 为body元素l定click事g
$("body").bind("click",function(){
var txt = $('#msg').html() + "<p>body元素被点?<p/>";
$('#msg').html(txt);
});
})
</script>
<script type="text/javascript">
$(function(){
// 为span元素l定click事g
$('span').bind("click",function(event){
var txt = $('#msg').html() + "<p>内层span元素被点?<p/>";
$('#msg').html(txt);
event.stopPropagation(); // L事g冒
});
// 为div元素l定click事g
$('#content').bind("click",function(event){
var txt = $('#msg').html() + "<p>外层div元素被点?<p/>";
$('#msg').html(txt);
event.stopPropagation(); // L事g冒
});
// 为body元素l定click事g
$("body").bind("click",function(){
var txt = $('#msg').html() + "<p>body元素被点?<p/>";
$('#msg').html(txt);
});
})
</script>
<script type="text/javascript">
$(function(){
$("#sub").bind("click",function(event){
var username = $("#username").val(); //获取元素的|val() Ҏ(gu)q回或设|被选元素的倹{?/span>
if(username==""){ //判断值是否ؓ(f)I?/span>
$("#msg").html("<p>文本框的g能ؓ(f)I?</p>"); //提示信息
event.preventDefault(); //L默认行ؓ(f) ( 表单提交 )
}
})
})
</script>
<body>
<form action="test.html">
用户名:(x)<input type="text" id="username" />
<br/>
<input type="submit" value="提交" id="sub"/>
</form>
<div id="msg"></div>
</body>
<script type="text/javascript">
$(function(){
$("#sub").bind("click",function(event){
var username = $("#username").val(); //获取元素的?/span>
if(username==""){ //判断值是否ؓ(f)I?/span>
$("#msg").html("<p>文本框的g能ؓ(f)I?</p>"); //提示信息
return false;
}
})
})
</script>
<script type="text/javascript">
$(function(){
// 为span元素l定click事g
$('span').bind("click",function(event){
var txt = $('#msg').html() + "<p>内层span元素被点?<p/>";
$('#msg').html(txt);
return false;
});
// 为div元素l定click事g
$('#content').bind("click",function(event){
var txt = $('#msg').html() + "<p>外层div元素被点?<p/>";
$('#msg').html(txt);
return false;
});
// 为body元素l定click事g
$("body").bind("click",function(){
var txt = $('#msg').html() + "<p>body元素被点?<p/>";
$('#msg').html(txt);
});
})
</script>
]]>
在看多核~程相关论文Ӟ往往一个ƈ发算法会(x)说自己是wait-free的或者lock-free的,或者是 non-blocking 的,q些专有词汇其实表示的是q发的程度,或者说q发的别。ƈ发别的理解是阅dUƈ发算法设计论文以及ƈ发数据结构实现的必备基础?/p>
]]>
无锁队列的实?/a>
锁无关的(Lock-Free)数据l构
An Introduction to Lock-Free Programming
]]>
建立socket后默认connect()函数为阻塞连接状态,在大多数实现中,connect的超时时间在75s臛_分钟之间Q想要羃短超时时_(d)可解决问题的两种Ҏ(gu)Q方法一、将socket句柄讄为非d状态,Ҏ(gu)二、采用信号处理函数设|阻塞超时控制?/strong>
在一个TCP套接口被讄为非d之后调用connect,connect?x)立卌回EINPROGRESS错误,表示q接操作正在q行?但是仍未完成;同时TCP的三路握手操作l进?在这之后,我们可以调用select来检查这个链接是否徏立成?非阻塞connect有三U用?
1.我们可以在三路握手的同时做一些其它的处理.connect操作要花一个往q时间完?而且可以是在M地方,从几个毫U的局域网到几百毫U或几秒的广域网.在这D|间内我们可能有一些其他的处理惌执行;
2.可以用这U技术同时徏立多个连?在Web览器中很普?
3.׃我们使用select来等待连接的完成,因此我们可以lselect讄一个时间限?从而羃短connect的超时时?在大多数实现?connect的超时时间在75U到几分钟之?有时候应用程序想要一个更短的时旉,使用非阻塞connect是一U方?
非阻塞connect听v来虽然简?但是仍然有一些细节问题要处理:
1.即套接口是非阻塞的,如果q接的服务器在同一CZ,那么在调用connect建立q接?q接通常?x)立卛_立成?我们必须处理q种情况;
2.源自Berkeley的实?和Posix.1g)有两条与select和非dIO相关的规?
A:当连接徏立成功时,套接口描q符变成可写;
B:当连接出错时,套接口描q符变成既可d可写;
注意:当一个套接口出错?它会(x)被select调用标记为既可读又可?
非阻塞connect有这么多好处,但是处理非阻塞connect时会(x)遇到很多可移植性问?
处理非阻塞connect的步?
W一?创徏socket,q回套接口描q符;
W二?调用fcntl把套接口描述W设|成非阻?
W三?调用connect开始徏立连?
W四?判断q接是否成功建立;
A:如果connectq回0,表示q接U成?服务器可客户端在同一台机器上时就有可能发生这U情?;
B:调用select来等待连接徏立成功完?
如果selectq回0,则表C徏立连接超?我们q回时错误l用?同时关闭q接,以防止三路握手操作l进行下?
如果selectq回大于0的?则需要检查套接口描述W是否可L可写;如果套接口描q符可读或可?则我们可以通过调用getsockopt来得到套接口上待处理的错?SO_ERROR),如果q接建立成功,q个错误值将?,如果建立q接旉到错?则这个值是q接错误所对应的errno?比如:ECONNREFUSED,ETIMEDOUT{?.
"d套接口上的错?是遇到的W一个可UL性问?如果出现问题,getsockopt源自Berkeley的实现是q回0,{待处理的错误在变量errno中返?但是Solaris?x)让getsockoptq回-1,errno|ؓ(f)待处理的错误;我们对这两种情况都要处理;
q样,在处理非dconnect?在不同的套接口实现的q_中存在的UL性问?首先,有可能在调用select之前,q接已l徏立成?而且Ҏ(gu)的数据已l到?在这U情况下,q接成功时套接口既可读又可?q和q接p|时是一L(fng).q个时候我们还得通过getsockopt来读取错误?q是W二个可UL性问?
UL性问题ȝ:
1.对于出错的套接口描述W?getsockopt的返回值源自Berkeley的实现是q回0,待处理的错误值存储在errno?而源自Solaris的实现是q回0,待处理的错误存储在errno?(套接口描q符出错时调用getsockopt的返回g可移?
2.有可能在调用select之前,q接已l徏立成?而且Ҏ(gu)的数据已l到?在这U情况下,套接口描q符是既可读又可?q与套接口描q符出错时是一L(fng);(怎样判断q接是否建立成功的条件不可移?
q样的话,在我们判断连接是否徏立成功的条g不唯一?我们可以有以下的Ҏ(gu)来解册个问?/font>:
1.调用getpeername代替getsockopt.如果调用getpeernamep|,getpeernameq回ENOTCONN,表示q接建立p|,我们必须以SO_ERROR调用getsockopt得到套接口描q符上的待处理错?
2.调用read,d长度?字节的数?如果read调用p|,则表C接徏立失?而且readq回的errno指明了连接失败的原因.如果q接建立成功,read应该q回0;
3.再调用一ơconnect.它应该失?如果错误errno是EISCONN,pC套接口已经建立,而且W一ơ连接是成功?否则,q接是p|?
被中断的connect:
如果在一个阻塞式套接口上调用connect,在TCP的三路握手操作完成之前被中断?比如?被捕L(fng)信号中断,会(x)发生什么呢?假定connect不会(x)自动重启,它将q回EINTR.那么,q个时?我们׃能再调用connect{待q接建立完成?如果再次调用connect来等待连接徏立完成的?connect会(x)q回错误值EADDRINUSE.在这U情况下,应该做的是调用select,像在非d式connect中所做的一?然后,select在连接徏立成?使套接口描述W可?或连接徏立失?使套接口描述W既可读又可?时返?
Ҏ(gu)二、定义信号处理函敎ͼ(x)
首先定义一个中断信号处理函数u_alarm_handlerQ用于超时后的报警处理,然后定义一?U的定时器,执行connectQ当pȝconnect成功Q则pȝ正常执行下去Q如果connect不成功阻塞在q里Q则过定义?U后Q系l会(x)产生一个信P触发执行u_alarm_handler函数Q?当执行完u_alarm_handler后,E序l从connect的下面一行执行下厅R?br />其中Q处理函数可以如下定义,也可以加入更多的错误处理?br />
|
|
|
pȝ~程c?/span>
《UNIX环境高~程》W.Richard StevensQ非常经典的书。虽然初学者就可以看,但是事实上它是《Unix Network Programing》的一本辅助资料。国内的译的《UNIX环境高~程》的水^不怎么P现在有媄印版Q直接读英文比读中文来得Ҏ(gu)?br />《Unix|络~程卷二》Unix|络~程L(fng)二卷没有涉及|络的东西,主要讲进E间通讯和PosixU程?/p>
|络~程c?/span>
《Unix|络~程》第一卯BSD Socket|络~程接口和另外一U网l编E接口的Q不q现在一般都用BSD SocketQ所以这本书只要看大U一半多可以了?br />《TCP/IP详解》一׃P卷一讲协议,卷二讲实玎ͼ卷三讲编E应用,也很l典的?br />《用TCP/IPq行|际互连》一׃P内容讲解十分_ֽ。卷一讲原理,卷二讲实玎ͼ卷三讲高U协议。感觉上q一套要比Stevens的那一套要好,pStevens也不得不承认它的W一卷非常经典。事实上Q第一卷即使你没有一点网l的知识Q看完以后也?x)对|络的来龙去脉了如指掌。第一卷中q有很多?fn)题也设计得l典和实用,因ؓ(f)作者本w就是一位教师,q且卷一是国外研I生的教材。习(fn)题ƈ没有{案Q留l读者思考,因ؓ(f)问题得答案可以让你成Z个中U的HackerQ这些问题的{案可以象Douglus索取Q不q只有他只给教师卷二我没有怎么看,卷三可以作ؓ(f)参考手册,其中C子也很经典?br />?!--StartFragment -->Linux 多线E服务端~程Q?muduo C++ |络库?
Linuxpȝ理c?/span>
《linuxpȝ理手册?br />《LINUX与UNIX SHELL~程指南?br />《Advanced Bash Scripting Guide?/p>
pȝ内核c?/span>
《Linux内核代码情景分析?br />《深入Linux内核源码?/p>
面向对象设计c?/span>
《设计模式?br />《敏捯Y件开发:(x)原则、模式与实践?br />《敏捷项目管理?/p>
内功修炼c?/strong>
《操作系l:(x)设计与实玎ͼW二版)?br />《操作系l概c?br />《数据结构与法-面向对象的C++设计模式?br />《编译原理》国防陈火旺
《离散数学及其应用?br />《计机l织与体pȝ?性能分析?br />《深入理解计机pȝ》【美】Randal E. Bryant David O'Hallaron著v
import java.util.*;
import java.io.*;
public class BadExecJavac
{
public static void main(String args[])
{
try
{
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("javac");
int exitVal = proc.exitValue();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t)
{
t.printStackTrace();
}
}
}
q行l果如下
E:\classes\com\javaworld\jpitfalls\article2>java BadExecJavacq是因ؓ(f)当进E还没有l束的情况下Q调用exitValueҎ(gu)?x)抛出IllegalThreadStateException.当然了我们会(x)问ؓ(f)什吗这个方法不?x)等到进E结束在q回一个合理的|
在检查Processcȝ所有可用方法以后我们发现WairFor()是一个更合适的Ҏ(gu)。事实上waitFor也会(x)q回exit value。这意味着你不可以同时用exitvalue和waitforQ而是只能选择一个?/p>
当然了也有情况你要在waitfor之前用exitvalueҎ(gu)Q就是你不想因ؓ(f)外部E序永远无法完成而一直等待下厅R?/p>
因此Z避免q个陷阱Q我们要么捕获IllegalThreadStateException异常Q要么等待进E完成。我们相当然的以为可以用waitfor来等待程序的l束。代码如下:(x)
import java.util.*;q次在linux下面q回的结果是2,而在windows下面据说E序?x)挂P关于其原因我们可以在jdk文档中找到部分解释:(x)因ؓ(f)一些操作系lؓ(f)标准的输入输Z仅提供有限的~冲区,当不能正的信息写q输入流或者从输出中获取信息Ӟ׃(x)D子进E的dQ甚x锁。现在我们就Ҏ(gu)jdk文档来处理javacq程的输出,当你不带M参数q行javacӞ它会(x)打印Zpd的有用的提示信息。而这些会(x)被传送到stderr中。我们可以写E序在其q回前获取这些信息。下面的代码提供了一个^庸的解决Ҏ(gu)?/p>import java.util.*;import java.io.*;
public class MediocreExecJavac{
public static void main(String args[]) {
try {
Runtime rt = Runtime.getRuntime();
Process proc = rt.exec("javac");
InputStream stderr = proc.getErrorStream();
InputStreamReader isr = new InputStreamReader(stderr);
BufferedReader br = new BufferedReader(isr);
String line = null;
System.out.println("<ERROR>");
while ( (line = br.readLine()) != null)
System.out.println(line);
System.out.println("</ERROR>");
int exitVal = proc.waitFor();
System.out.println("Process exitValue: " + exitVal);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
q次E序可以正确的输Z提示信息Q但是我们应该注意到其返回代码是2Q我们知道Q何非0的返回代码都表示E序不正常。所以我们需要进一步的查找原因。对于win32而言是file not foundQ很明显javac期望我们提供~译的文件。所以对于永q挂L(fng)问题Q如果你q行的程序会(x)有输出或者要求输出入Ӟ你需要处理输出和输入。我在linux下面q行的结果是正确的。前面说了在win32下面2代表是文件没有找刎ͼ而在q种情况下表明是dir.exe没有扑ֈQ(因ؓ(f)Ҏ(gu)没有这个文Ӟ他们都被装到common.com Qwin95Q或者cmd.exe中了?/p>
下面我们列出一个正的处理Process的输入输出流的方法。需要用一个线E类?/p>
import java.util.*;
import java.io.*;
class StreamGobbler extends Thread{
InputStream is;
String type;
StreamGobbler(InputStream is, String type) {
this.is = is;
this.type = type;
}
public void run() {
try {
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line=null;
while ( (line = br.readLine()) != null)
System.out.println(type + ">" + line);
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
用于专门的处理输入输出?/p>
public class GoodWindowsExec{
public static void main(String args[]) {
if (args.length < 1) {
System.out.println("USAGE: java GoodWindowsExec <cmd>");
System.exit(1);
}
try {
String osName = System.getProperty("os.name" );
String[] cmd = new String[3];
if( osName.equals( "Windows NT" ) ) {
cmd[0] = "cmd.exe" ;
cmd[1] = "/C" ;
cmd[2] = args[0];
} else if( osName.equals( "Windows 95" ) ) {
cmd[0] = "command.com" ;
cmd[1] = "/C" ;
cmd[2] = args[0]; }
Runtime rt = Runtime.getRuntime();
System.out.println("Execing " + cmd[0] + " " + cmd[1] + " " + cmd[2]);
Process proc = rt.exec(cmd); // any error message?
StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream(), "ERROR"); // any output?
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream(), "OUTPUT"); // kick them off
errorGobbler.start();
outputGobbler.start(); // any error???
int exitVal = proc.waitFor();
System.out.println("ExitValue: " + exitVal);
} catch (Throwable t) {
t.printStackTrace();
}
}
}
如果q行如下命o(h)上面的代码会(x)调用wordE序
>java GoodWindowExec “abc.doc”
也就是说文gcd如果window能够识别它就?x)调用对应的E序处理?/p>
StreamGlobbler的最重要作用是他?x)清I所有的传递给他的inputstreamQ这样不?x)造成Processd或者死锁?/p>