搜索
bottom↓
回复: 7

问个protothread问题

[复制链接]

出0入0汤圆

发表于 2012-2-28 11:29:45 | 显示全部楼层 |阅读模式
#define PT_END(pt) LC_END((pt)->lc); PT_YIELD_FLAG = 0; \
                   PT_INIT(pt); return PT_ENDED; }

#define PT_WAIT_UNTIL(pt, condition)         \
  do { \
    LC_SET((pt)->lc); \
    if(!(condition)) { \
      return PT_WAITING; \
    } \
  } while(0)

---------------------------------------以上是源码
我想提2个问题:
1.PT_YIELD_FLAG = 0; 这句好像没有任何用处,它是局部变量,线程退出后自动销毁,干么给他赋值0,再退出销毁呢?
2.第二个宏定义中  do{}while(0)这种结构貌似可以不要,作者为什么这样写呢?

阿莫论坛20周年了!感谢大家的支持与爱护!!

你熬了10碗粥,别人一桶水倒进去,淘走90碗,剩下10碗给你,你看似没亏,其实你那10碗已经没有之前的裹腹了,人家的一桶水换90碗,继续卖。说白了,通货膨胀就是,你的钱是挣来的,他的钱是印来的,掺和在一起,你的钱就贬值了。

出0入0汤圆

发表于 2012-2-28 11:41:08 | 显示全部楼层
1.PT_YIELD_FLAG = 0; 这句好像没有任何用处,它是局部变量,线程退出后自动销毁,干么给他赋值0,再退出销毁呢?   
---------------------------------------------------------------------------------
PT_YIELD_FLAG貌似作为thread等待子thread用的。


2.第二个宏定义中  do{}while(0)这种结构貌似可以不要,作者为什么这样写呢?
do{  }while(0)能把多个语句合成一个语句,并且还必须需要后面的;

出0入0汤圆

发表于 2012-2-28 12:25:26 | 显示全部楼层
1.
PT_YIELD_FLAG是局部的(初始化为1),这个变量在调用PT_YIELD*()时会被置0,然后将lc指向下一行,最后由这句
if(PT_YIELD_FLAG == 0) { return 1; } // --- (1)
来结束。

这样,当下次恢复的时候,PT_YIELD_FLAG首先被初始化为1,然后跳到(1)行
由于不满足条件,使之可以继续执行。


2.
假设某人这样写:
if (xxx)
   PT_WAIT_UNTIL(xxx);

不加do { }while(0), 你看看展开后会造成什么后果

出0入0汤圆

 楼主| 发表于 2012-2-28 14:25:20 | 显示全部楼层
这样,当下次恢复的时候,PT_YIELD_FLAG首先被初始化为1,然后跳到(1)行
由于不满足条件,使之可以继续执行。

-----------------------------------------------------------------------
下次重新恢复的时候,因为PT_BEGIN每次都执行,实际上重新定义了一个局部变量PT_YIELD_FLAG,PT_END退出时,已经吧PT_YIELD_FLAG这个栈上的变量销毁了,下次执行PT_BEGIN时,PT_YIELD_FLAG在栈上的位置可能已经发生了变化,所以二者名字相同,其实不是一个变量,它是局部变量,线程退出后自动销毁,干么给他赋值0,再退出销毁呢?


do { }while(0), 那个,theophilus 说的很有道理,那么可以支架{},不加do和while(0)了。。

出0入0汤圆

发表于 2012-2-28 15:01:11 | 显示全部楼层
理论上确实是不需要的,PT_YIELD_FLAG只是一个HACK.
你需要仔细看看宏定义,另外,如果你用gcc的话,可以用 gcc 的 -E -P 来输出展开宏之后的代码,方便分析

比如下例:
#include "pt.h"

static PT_THREAD(blah(struct pt *pt))
{
    static int delay;

    PT_BEGIN(pt);

    for(delay = 1234; delay > 0; delay -= 1) {
        // do something
        // ...
        // NOTE: Yield here
        PT_YIELD(pt);
    }

    PT_END(pt);
}

展开后:

typedef unsigned short lc_t;
struct pt {
  lc_t lc;
};
static char blah(struct pt *pt)
{
    static int delay;
    { char PT_YIELD_FLAG = 1; switch((pt)->lc) { case 0:; // 这里先让PT_YIELD_FLAG = 1, 再执行跳转
    for(delay = 1234; delay > 0; delay -= 1) {



        do { PT_YIELD_FLAG = 0; (pt)->lc = 13; case 13:; if(PT_YIELD_FLAG == 0) { return 1; } } while(0); // 注意这一行
    }

    }; PT_YIELD_FLAG = 0; (pt)->lc = 0;; return 3; };
}


主要注意红色这一行,"(pt)->lc = 13" 和 "case 13:",你要分析一下两次执行blah()会发生什么情况。
其实有办法让 (pt)->lc 等于跳过 "return 1" 下面一句的行标,PT_YIELD_FLAG 就完全不需要了,只是宏定义起来不会优雅。

出0入0汤圆

发表于 2012-2-28 15:39:33 | 显示全部楼层
回复【3楼】jishanlaike  阿弱
这样,当下次恢复的时候,pt_yield_flag首先被初始化为1,然后跳到(1)行
由于不满足条件,使之可以继续执行。
-----------------------------------------------------------------------
下次重新恢复的时候,因为pt_begin每次都执行,实际上重新定义了一个局部变量pt_yield_flag,pt_end退出时,已经吧pt_yield_flag这个栈上的变量销毁了,下次执行pt_begin时,pt_yield_flag在栈上的位置可能已经发生了变化,所以二者名字相同,其实不是一个变量,它是局部变量,线程退出后自动销毁,干么给他赋值0,再退出销毁呢?
do { }while(0), 那个,theophilus 说的很有道理,那么可以支架{},不加do和while(0)了。。

-----------------------------------------------------------------------

不要直接用 {}
比如
#define XXX() { /* ... */ }

if (xxx)
   XXX();
else
   one();

展开后, '}'后面, else前面会多一个分号,照样出错。

出0入0汤圆

 楼主| 发表于 2012-2-29 11:47:41 | 显示全部楼层
theophilus:非常感谢!

static char blah(struct pt *pt)
{
    static int delay;
    { char PT_YIELD_FLAG = 1; switch((pt)->lc) { case 0:;  
    for(delay = 1234; delay > 0; delay -= 1) {



        do { PT_YIELD_FLAG = 0; (pt)->lc = 13; case 13:; if(PT_YIELD_FLAG == 0) { return 1; } } while(0);
    }

    }; PT_YIELD_FLAG = 0; (pt)->lc = 0;; return 3; };   // 我的意思是:这行的PT_YIELD_FLAG = 0;好像没有任何用处,可以省略?
}

出0入0汤圆

发表于 2012-2-29 15:21:12 | 显示全部楼层
这里是没有用。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片。注意:要连续压缩2次才能满足要求!!】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-10-3 02:37

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表