请分析李经理在李参 时间管理方法上存在哪些问题

鱼子酱(Caviar),又称鱼籽酱,在波斯语中意为鱼卵,严格来说,只有鲟鱼卵才可称为鱼子酱。鱼子酱作为特权阶级几个世纪以来追捧的珍馐美味,也被称为「黑金」。鱼子酱为啥贵,鱼子酱怎么吃,鱼子酱的做法,带着疑问和你深挖背后的故事。
在此可输入您对该资料的评论~
(window.slotbydup = window.slotbydup || []).push({
id: '4540180',
container: s,
size: '250,200',
display: 'inlay-fix'
热门资料排行
添加成功至
资料评价:
所需积分:0& & & &&转载请注明出处:&
基本时间操作函数:
& & & &&Libevent采用的时间类型是struct& timeval,这个类型在很多平台都提供了。此外,Libevent还提供了一系列的时间操作函数。比如两个struct timeval相加、相减、比较大小。有些平台直接提供了一些时间操作函数,但有些则没有,那么Libevent就自己实现。这些宏如下:
#ifdef _EVENT_HAVE_TIMERADD
#define evutil_timeradd(tvp, uvp, vvp) timeradd((tvp), (uvp), (vvp))
#define evutil_timersub(tvp, uvp, vvp) timersub((tvp), (uvp), (vvp))
#define evutil_timeradd(tvp, uvp, vvp)
(vvp)-&tv_sec = (tvp)-&tv_sec + (uvp)-&tv_
(vvp)-&tv_usec = (tvp)-&tv_usec + (uvp)-&tv_
if ((vvp)-&tv_usec &= 1000000) {
(vvp)-&tv_sec++;
(vvp)-&tv_usec -= 1000000;
} while (0)
#define evutil_timersub(tvp, uvp, vvp)
(vvp)-&tv_sec = (tvp)-&tv_sec - (uvp)-&tv_
(vvp)-&tv_usec = (tvp)-&tv_usec - (uvp)-&tv_ \
if ((vvp)-&tv_usec & 0) {
(vvp)-&tv_sec--;
(vvp)-&tv_usec += 1000000;
} while (0)
#ifdef _EVENT_HAVE_TIMERCLEAR
#define evutil_timerclear(tvp) timerclear(tvp)
#define evutil_timerclear(tvp) (tvp)-&tv_sec = (tvp)-&tv_usec = 0
#define evutil_timercmp(tvp, uvp, cmp)
(((tvp)-&tv_sec == (uvp)-&tv_sec) ?
((tvp)-&tv_usec cmp (uvp)-&tv_usec) :
((tvp)-&tv_sec cmp (uvp)-&tv_sec))
#ifdef _EVENT_HAVE_TIMERISSET
#define evutil_timerisset(tvp) timerisset(tvp)
#define evutil_timerisset(tvp) ((tvp)-&tv_sec || (tvp)-&tv_usec)
& & & &&代码中的那些条件宏,是在配置Libevent的时候检查所在的系统环境而定义的。具体的内容,可以参考《》一文。
& & & &&Libevent的时间一般是用在超时event的。对于超时event,用户只需给出一个超时时间,比如多少秒,而不是一个绝对时间。但在Libevent内部,要将这个时间转换成绝对时间。所以在Libevent内部会经常获取系统时间(绝对时间),然后进行一些处理,比如,转换、比较。
cache时间:
& & & &&Libevent封装了一个evutil_gettimeofday函数用来获取系统时间,该函数在POSIX的系统是直接调用gettimeofday函数,在Windows系统是通过_ftime函数。虽然gettimeofday的,不过Libevent还是使用了一个cache保存时间,使得更加高效。在event_base结构体有一个struct
timeval类型的cache变量 tv_cache。处理超时event的两个函数event_add_internal和event_base_loop内部都是调用gettime函数获取时间的。gettime函数如下:
//event.c文件
static int
gettime(struct event_base *base, struct timeval *tp)
if (base-&tv_cache.tv_sec) { //cache可用
*tp = base-&tv_
return (0);
…//没有cache的时候就使用其他方式获取时间
& & & &&从上面代码可以看到,Libevent优先使用cache时间。tv_bache变量处理作为cache外,还有另外一个作用,下面会讲到。
& & & &&cache的时间也是通过调用系统的提供的时间函数得到的。
//event.c文件
static inline void
update_time_cache(struct event_base *base)
base-&tv_cache.tv_sec = 0;
if (!(base-&flags & EVENT_BASE_FLAG_NO_CACHE_TIME))
gettime(base, &base-&tv_cache);
& & & &&tv_cache是通过调用gettime来获取时间。由于tv_cache.tv_sec已经赋值为0,所以它将使用系统提供的时间函数得到时间。代码也展示了,如果event_base的配置中定义了EVENT_BASE_FLAG_NO_CACHE_TIME宏,将不能使用cache时间。关于这个宏的设置可以参考《》一文。
处理用户手动修改系统时间:
& & & &&如果用户能老老实实,或许代码就不需要写得很复杂。由于用户的不老实,所以有时候要考虑很多很特殊的情况。在Libevent的时间管理这方面也是如此。
& & & &&Libevent在实际使用时还有一个坑爹的现象,那就是,用户手动把时钟(wall time)往回调了。比如说现在是上午9点,但用户却把OS的系统时间调成了上午7点。这是很坑爹的。对于超时event和event_add的第二个参数,都是一个时间长度。但在内部Libevent要把这个时间转换成绝对时间。
&& & & &&如果用户手动修改了OS的系统时间。那么Libevent把超时时间长度转换成绝对时间将是弄巧成拙。拿上面的时间例子。如果用户设置的超时为1分钟。那么到了9:01就会超时。如果用户把系统时间调成了7点,那么要过2个小时01分才能发生超时。这就和用户原先的设置差得很远了。
& & & &&读者可能会说,这个责任应该是由用户负。呵呵,但Libevent提供的函数接口是一个时间长度,既然是时间长度,那么无论用户怎么改变OS的系统时间,这个时间长度都是相对于event_add ()被调用的那一刻算起,这是不会变的。如果Libevent做不到这一点,这说明是Libevent没有遵循接口要求。
& & & &&为此,Libevent提出了一些解决方案。
使用monotonic时间:
& & & &&问题的由来是因为用户能修改系统时间,所以最简单的解决方案就是能获取到一个用户不能修改的时间,然后以之为绝对时间。因为event_add提供给用户的接口使用的是一个时间长度,所以无论是使用哪个绝对时间都是无所谓的。
& & & &&基于这一点,Libevent找到了monotonic时间,从字面来看monotonic翻译成单调。我们高中学过的单调函数英文名就是monotonic function。monotonic时间就像单调递增函数那样,只增不减的,没有人能手动修改之。
&& & & &monotonic时间是boot启动后到现在的时间。用户是不能修改这个时间。如果Libevent所在的系统支持monotonic时间的话,那么Libevent就会选用这个monotonic时间为绝对时间。
& & & &&首先,Libevent检查所在的系统是否支持monotonic时间。在event_base_new_with_config函数中会调用detect_monotonic函数检测。
//event.c文件
static void
detect_monotonic(void)
#if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
struct timespec
static int use_monotonic_initialized = 0;
if (use_monotonic_initialized)
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
use_monotonic = 1; //系统支持monotonic时间
use_monotonic_initialized = 1;
& & & &&从上面代码可以看到,如果Libevent所在的系统支持monotonic时间,就将全局变量use_monotonic赋值1,作为标志。
& & & &&如果Libevent所在的系统支持monotonic时间,那么Libevent将使用monotonic时间,也就是说Libevent用于获取系统时间的函数gettime将由monotonic提供时间。
//event.c文件
static int
gettime(struct event_base *base, struct timeval *tp)
EVENT_BASE_ASSERT_LOCKED(base);
if (base-&tv_cache.tv_sec) {
*tp = base-&tv_
return (0);
#if defined(_EVENT_HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC)
if (use_monotonic) {
struct timespec
if (clock_gettime(CLOCK_MONOTONIC, &ts) == -1)
return (-1);
tp-&tv_sec = ts.tv_
tp-&tv_usec = ts.tv_nsec / 1000;
//额外的功能
if (base-&last_updated_clock_diff + CLOCK_SYNC_INTERVAL
& ts.tv_sec) {
evutil_gettimeofday(&tv,NULL);
//tv_clock_diff记录两种时间的时间差
evutil_timersub(&tv, tp, &base-&tv_clock_diff);
base-&last_updated_clock_diff = ts.tv_
return (0);
//如果所在的系统不支持monotonic时间,那么只能使用evutil_gettimeofday了
return (evutil_gettimeofday(tp, NULL));
& & & &&上面的代码虽然首先是使用cache时间,但实际上event_base结构体的cache时间也是通过调用gettime函数而得到的。上面代码也可以看到:如果所在的系统没有提供monotonic时间,那么就只能使用evutil_gettimeofday这个函数提供的系统时间了。
& & & &&从上面的分析可知,如果Libevent所在的系统支持monotonic时间,那么根本就不用考虑用户手动修改系统时间这坑爹的事情。但如果所在的系统没有支持monotonic时间,那么Libevent就只能使用evutil_gettimeofday获取一个用户能修改的时间。
尽可能精确记录时间差:
& & & &&现在来看一下Libevent在这种情况下在怎么解决这个坑爹得的问题。
& & & &&&Libevent给出的方案是,尽可能精确地计算 用户往回调了多长时间。如果知道了用户往回调了多长时间,那么将小根堆中的全部event的时间都往回调一样的时间即可。Libevent调用timeout_correct函数处理这个问题。
//event.c文件
static void
timeout_correct(struct event_base *base, struct timeval *tv)
/* Caller must hold th_base_lock. */
struct event **
//如果系统支持monotonic时间,那么就不需要校准时间了
if (use_monotonic)
//获取现在的系统时间
gettime(base, tv);
//tv的时间更大,说明用户没有往回调系统时间。那么不需要处理
if (evutil_timercmp(tv, &base-&event_tv, &=)) {
base-&event_tv = *
evutil_timersub(&base-&event_tv, tv, &off);//off差值,即用户调小了多少
pev = base-&timeheap.p;
size = base-&timeheap.n;
//用户已经修改了OS的系统时间。现在需要对小根堆的所有event
//都修改时间。使得之适应新的系统时间
for (; size-- & 0; ++pev) {
struct timeval *ev_tv = &(**pev).ev_
//前面已经用off保存了,用户调小了多少。现在只需
//将小根堆的所有event的超时时间(绝对时间)都减去这个off即可
evutil_timersub(ev_tv, &off, ev_tv);
//保存现在的系统时间。以防用户再次修改系统时间
base-&event_tv = *
& & & &&Libevent用event_base的成员变量event_tv保存用户修改系统时间前的系统时间。如果刚保存完,用户就修改系统时间,这样就能精确地计算出用户往回调了多长时间。但毕竟Libevent是用户态的库,不能做到用户修改系统时间前的一刻保存系统时间。
& & & &&于是Libevent采用多采点的方式,即时不时就保存一次系统时间。所以在event_base_loop函数中的while循环体里面会有gettime(base, &base-&event_tv);这是为了能多采点。但这个while循环里面还会执行多路IO复用函数和处理被激活event的回调函数(这个回调函数执行多久也是个未知数)。这两个函数的执行需要的时间可能会比较长,如果用户刚才是在执行完这两个函数之后修改系统时间,那么event_tv保存的时间就不怎么精确了。这也是没有办法的啊!!唉!!
& & & &&下面贴出event_base_loop函数
//event.c文件
event_base_loop(struct event_base *base, int flags)
const struct eventop *evsel = base-&
struct timeval *tv_p;
int res, done, retval = 0;
//要使用cache时间,得在配置event_base时,没有加入EVENT_BASE_FLAG_NO_CACHE_TIME选项
clear_time_cache(base);
while (!done) {
timeout_correct(base, &tv);
if (!N_ACTIVE_CALLBACKS(base) && !(flags & EVLOOP_NONBLOCK)) {
//参考http://blog.csdn.net/luotuo44/article/details/
timeout_next(base, &tv_p); //获取dispatch的最大等待时间
evutil_timerclear(&tv);
//保存系统时间。如果有cache,将保存cache时间。
gettime(base, &base-&event_tv);
//之所以要在进入dispatch之前清零,是因为进入
//dispatch后,可能会等待一段时间。cache就没有意义了。
//如果第二个线程此时想add一个event到这个event_base里面,在
//event_add_internal函数中会调用gettime。如果cache不清零,
//那么将会取这个cache时间。这将取一个不准确的时间。
clear_time_cache(base);
//多路IO复用函数
res = evsel-&dispatch(base, tv_p);
//将系统时间赋值到cache中
update_time_cache(base);
//处理超时事件。参考http://blog.csdn.net/luotuo44/article/details/
timeout_process(base);
if (N_ACTIVE_CALLBACKS(base)) {
int n = event_process_active(base);//处理激活event
return (retval);
& & & &&可以看到,在dispatch和event_process_active之间有一个update_time_cache。而前面的gettime(base,&base-&event_tv);实际上取的就是cache的时间。所以,如果该Libevent支持cache的话,会精确那么一些。一般来说,用户为event设置的回调函数,不应该执行太久的时间。这也是tv_cache时间的另外一个作用。
出现的bug:
& & & &&由于Libevent的解决方法并不是很精确,所以还是会有一些bug。下面给出一个bug。如果用户是在调用event_new函数之后,event_add之前对系统时间进行修改,那么无论用户设置的event超时有多长,都会马上触发超时。下面给出实际的例子。这个例子要运行在不支持monotonic时间的系统,我是在Windows运行的。
#include &event2/event.h&
#include&stdio.h&
void timeout_cb(int fd, short event, void *arg)
printf(&in the timeout_cb\n&);
int main()
struct event_base *base = event_base_new();
struct event *ev = event_new(base, -1, EV_TIMEOUT, timeout_cb, NULL);
//暂停,让用户有时间修改系统时间。可以将系统时间往前1个小时
scanf(&%c&, &ch);
struct timeval tv = {100, 0};//这个超时时长要比较长。这里取100秒
//第二个参数不能为NULL.不然也是不能触发超时的。毕竟没有时间
event_add(ev, &tv);
event_base_dispatch(base);
& & & &&这个bug的出现是因为,在event_base_new_with_config函数中有gettime(base,&base-&event_tv),所以event_tv记录了修改前的时间。而event_add是在修改系统时间后才调用的。所以event结构体的ev_timeout变量使用的是修改系统时间后的超时时间,这是正确的时间。在执行timeout_correct函数时,Libevent发现用户修改了系统时间,所以就将本来正确的ev_timeout减去了off。所以ev_timeout就变得比较修改后的系统时间小了。在后面检查超时时,就会发现该event已经超时了(实际是没有超时),就把它触发。
& & & &&如果该event有EV_PERSIST属性,那么之后的超时则会是正确的。这个留给读者去分析吧。
& & & &&另外,Libevent并没有考虑把时钟往后调,比如现在是9点,用户把系统时间调成10点。上面的代码如果用户是在event_add之后修改系统时间,就能发现这个bug。
本文已收录于以下专栏:
相关文章推荐
转载至:.cn/s/blog_56dee71a0100qx4s.html
很多时候,除了响应事件之外,应用还希望做一定的数据缓冲。比如说,写入数据的时候,...
Libevent定义了一些日志类型。
#define EVENT_LOG_DEBUG 0
#define EVENT_LOG_MSG   1
#define EVENT_LOG_WARN  2
...
memcache研究
最近开发了一个数据库,该数据库是利用共享内存做的,测试了下增删改查的性能,想与memcached数据库做个对比,故研究下memcached。
那什么是memcached?
理大并发之五 使用libevent利器bufferevent
         首先来翻译一段文章
         你可能注意到随着我...
处理大并发之五 使用libevent利器bufferevent
         首先来翻译一段文章
         你可能注意到...
努力吧,现在也不晚
来自http://blog.csdn.net/shuaihj/article/details/8586101
或许这再一次印证任何人每一次的成功背后都有不为人知的付出和汗水。   ...
在前一篇博文可以看到很多函数在操作前都需要对这个evbuffer进行加锁。同event_base不同,如果evbuffer支持锁的话,要显式地调用函数evbuffer_enable...
libevent的evbuffer实现了为向后面添加数据和从前面移除数据而优化的字节队列。
evbuffer用于处理缓冲网络IO的“缓冲”部分。它不提供调度IO或者当IO就绪时触发IO的功能:这是b...
他的最新文章
讲师:汪剑
讲师:刘道宽
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)“加减时光”:时间管理混乱者的需求或为日程建议和分析_网易新闻
“加减时光”:时间管理混乱者的需求或为日程建议和分析
用微信扫码二维码
分享至好友和朋友圈
(原标题:“加减时光”:时间管理混乱者的需求或为日程建议和分析)
人们越来越多的时间被手机内的App占用了。2016年5月,调查机构发起“手机App调查”,采集近6000份样本,分析得出45.39%的网友手机里有35-40个App,生活类App停留时间最长,然后是社交类、娱乐类、教育类App。 所以,时间管理需求越来越明显,而且利用App应用管理时间似乎更能解决这一需求。发现这一市场需求的许多创业者开始开发一系列时间应用App,试图为人们“安排日程”、“管理时间支出”。
l 各有分工的“时间管理”App
有一部分是管理时间效率的应用。
钻研过时间管理的用户,肯定知道“番茄时间管理法”——一种监督你的工作效率的方法,随之诞生的番茄时间、番茄土豆时间等等App致力于让你将工作时间主动碎片化,再将其碎片化管理。App其实不错,仍有许多“半途而废”的用户,他们表示工作中的干扰因素太多,没法坚持。还有部分用户说,真正的时间管理需要的不是管理工作,而是“生活”。
也有的App可以告诉你“时间都去哪儿了”。
这些应用告诉你每日、每月的时间分配大概比例,这一直是人们在时间应用上的缺陷,所以出现的时候许多人直呼这正是他们所需要的。可是目前的分类只能按照用户存入的项目进行分类,如果每次输入的不同,分类起来仍和行程单的差别不大。
其实,有那么一部分世间管理混乱者,他们更看重对生活日程而非工作日程的管理。目前对于这部分人群的时间应用几乎不存在。
l 究竟什么是“时间管理”
这部分人群关注的是:给予日程建议,能够发起社交性日程;对于时间支出进行分析。
所谓建议,是指在日程内容上给予建议,能够得到朋友、工作乃至其他分类日程的邀请,也就是社交性日程。
应对这两点需求,一款名为sunrise的应用在一些个性化建议上比较突出,它被品玩报道过,并且被微软收购了,不过它是为美国人民生活习惯设计的。但是,日它将正式关闭。
国内的话,6月1日上线Apple AppStore的“加减时光”,可以实现Microsoft Outlook、Google Calendar等主流应用的一键同步,也拥有对工作、生活日程管理的功能。
这款应用根据使用者的日程安排情况、地理位置以及积累一定数据之后的兴趣爱好,为没时间的人安排事情,为有时间的人推荐活动,丰满用户空白的时间线。发起活动方面,“加减时光”分别引入个体社交的活动发起、邀请机制,群体社交的活动推荐、分享机制。个体社交邀请通过客户端、手机、邮件同时送达用户或非用户手中;群体社交邀请一键分享邀请函,清爽优雅的函件图片不用繁杂的打开链接,主题、时间、地点一目了然。
所谓分析,则是对花出去时间的解析。
我们深知录入到解析的“计算器功能”绝不是智能时代的“时间管理”。加减时光会根据用户的日程内容和共同参与对象进行分类,让你不仅知道“时间去哪儿了”也知道“时间去谁那儿了”,从而客观、真实的记录一切时间支出,也不需要用户专门操心反复录入。
工作、生活的日程管理一直是用户的痛点,其中工作日程管理已经有了番茄土豆等不错的应用,生活日程管理上加减时光和sunrise则是这类应用中的佼佼者,一款更适用于中国用户,一款已经被Microsoft融入Outlook中,当然这两款应用也同时为工作日程服务。
【免责声明】本文仅代表作者本人观点,与重庆晚报、第一眼网站无关。第一眼网站对文中陈述、观点判断保持中立,不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。请读者仅作参考,并请自行承担全部责任。
本文来源:华龙网-重庆晚报
责任编辑:王晓易_NE0011
用微信扫码二维码
分享至好友和朋友圈
加载更多新闻
热门产品:   
:        
:         
热门影院:
阅读下一篇
用微信扫描二维码
分享至好友和朋友圈时间管理的方法与技巧分析.ppt
您当前位置:
标签:& 共30页|上传时间: 15:59:04
您电脑的flash版本过底,或没有安装flash,请点击以下图标下载安装flash插件
文档加载中
广告倒计时 秒
用户名:游客
评论内容不能少于10个子}

我要回帖

更多关于 仓库管理存在问题 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信