8种机械键盘轴体对比
本人程序员,要买一个写代码的键盘,请问红轴和茶轴怎么选?
函数pthread_cancel向由参数thread指定的线程发送一个取消请求。
#include
int pthread_cancel(pthread_t thread);
/* 成功返回0,失败返回正的errno值 */
发出取消请求后,函数pthread_cancel立即返回,不会等待目标线程的退出。
取消状态及类型
#include
int pthread_setcancelstate(int state, int *oldstate);
int pthread_setcanceltype(int type, int *oldtype);
/* 成功返回0,失败返回正的errno值 */
函数pthread_setcancelstate会将调用线程的取消状态设置为参数state所给定的值。该参数的取值可能如下:
PTHREAD_CANCEL_DISABLE
线程不可取消。如果此类线程收到取消请求,则会将请求挂起,直至将线程的取消状态置为启用。
如果线程执行的代码片段需要不间断的一气呵成,那么临时屏蔽线程的取消状态就变的很有必要。
PTHREAD_CANCEL_ENABLE
线程可以取消。这是新建线程取消状态的默认值。
如果线程的取消性状态为启用,那么对取消请求的处理则取决于线程的取消性类型。该类型可以通过调用pthread_setcanceltype指定。参数type有如下值:
PTHREAD_CANCEL_ASYNCHRONOUS
可能会在任何时点(也许是立即取消,但不一定)取消线程。异步取消的应用场景很少。
PTHREAD_CANCEL_DEFERED
取消请求保持挂起,直至到达取消点(cancellation point)。这也是新建线程的缺省类型。
当某线程调用fork时,子进程会继承调用线程的取消性类型及状态。
当某线程调用exec时,会将新程序主线程的取消性及类型分别重置为PTHREAD_CANCEL_ENABLE和PTHREAD_CANCEL_DEFERED。
取消点
若将线程的取消性状态和类型分别设置为启用和延迟,仅当线程抵达某个取消点时,线程取消请求才会起作用。
SUSv3规定,若实现提供了如下函数,则这些函数必须是取消点。
除以上函数以外,SUSv3还规定了大量函数,系统实现可以将其定义为取消点。可移植应用程序必须正确处理这一情况:线程在调用这些函数时,有可能遭到取消。
SUSv3规定,除了上述两组必须或可能是取消点的函数之外,不得将标准中的任何其他函数视为取消点(亦即,调用这些函数不会招致线程取消,应用程序无需加以处理)。系统实现可随意将标准并未规范的其他函数标记为取消点。
线程一旦收到取消请求,且启用了取消性状态并将类型设置为延迟,则其会在下次抵达取消点时终止。如果该线程尚未分离,那么为防止其变为僵尸线程,必须由其他线程对其进行连接(join)。连接之后,返回至函数pthread_join中第二个参数的将是一个特殊值PTRHEAD_CANCELED。
线程可取消性的检测
假设程序执行的是一个不含取消点的计算密集型循环,这时,线程永远不会相应取消请求。
#include
void pthread_testcancel(void);
函数pthread_testcancel的目的很简单,就是产生一个取消点。线程如果已有处于挂起状态的取消请求,那么只要调用该函数,线程就会随之终止。
清理函数(cleanup handler)
线程可以设置一个或多个清理函数,当线程遭取消时会自动运行这些函数,在线程终止之前可执行诸如修改全局变量,解锁互斥锁等操作。
每个线程都可以拥有一个清理函数栈。当线程遭取消时,会延该栈自顶向下依次执行清理函数,首先会执行最近设置的函数,接着是次新的函数,以此类推。当执行完所有的清理函数后,线程终止。
#include
void pthread_cleanup_push(void (*routine)(void *), void *arg);
void pthread_cleanup_pop(int execute);
pthread_cleanup_push会将参数routine所指向的函数添加到调用线程的清理函数栈顶。
通常,线程若在执行一段特殊代码时遭到取消,才需要执行清理动作。如果线程顺利执行完这段code而未遭到取消,那么就不在需要清理。所以,每个对pthread_cleanup_push的调用都会伴随着pthread_cleanup_pop的调用。此函数从清理函数栈顶移除一个函数,如果参数execute非0,那么无论如何都会执行清理函数。在线程未遭取消而又希望执行清理动作时,这会非常方便。
为了便于编码,若线程因调用pthread_exit而终止,则也会执行清理函数栈中的清理函数。线程正常返回(return)时不会执行清理函数。
异步取消
如果设置线程为可异步取消时(取消性类型为PTHREAD_CANCEL_ASYNCHRONOUS),可以在任何时间点将其取消,取消动作不会拖延到下一个取消点才进行。
异步取消的问题在于,尽管清理函数依然会得以执行,但清理函数却无从得知线程的具体状态(延迟取消只会在取消点取消,线程状态已知)。换句话说,清理函数不清楚需要执行哪些清理步骤,另外,线程也有可能在malloc的调用期间被取消,这极有可能造成后续的混乱。
作为一般性原则,可异步取消的线程不应该分配任何资源,也不能获取互斥量或锁。这导致大量库函数无法使用。换言之,异步取消功能鲜有应用场景,其中之一就是:取消在执行计算密集型循环的线程。
总结
函数pthread_cancel允许某线程向另一个线程发送取消请求,请求目标线程取消(终止)。
目标线程如何响应,取决于其取消性状态和类型。如果禁用线程的取消性状态,那么请求会保持挂起(pending)状态,直至将线程的取消性状态置为启用。如果启用取消性状态,那么线程何时响应取消请求取决于取消性类型。若类型为延迟取消,则在线程到达取消点时,取消发生。如果为异步取消类型,取消动作随时可能发生(鲜有使用)。
线程可以设置一个清理函数栈,当线程遭到取消(或调用pthread_exit)时,会自动调用这些函数以执行清理工作。