谁能告诉我如何插入函数调用(比如Yield()
在C函数内随机的地方,所以每个代码运行时间, Yield()
会从代码的不同部分叫什么?
我为我使用2个线程在协作线程环境中 ,除非正在运行的线程得到的处理器明确,其他(等待)线程无法开始运行面临着这样的要求。 我不想放置Yield()
调用在一个单点,因为这使得线程序列确定性。 无需重新布线的整个环境(从合作先发制人),这是我能想到的,其中Thread_1()使得唯一的解决办法Yield()
在里面随意地呼叫,并允许Thread_2()接管。
任何见解不同的解决方案实现相同的最终目标也欢迎!
一个BFI解决方案要求,我想
我想你将不得不解决这个明显的方式。 您将需要为一个包装Yield()
使上是否调用真实的东西“随机”的决定。
如果你不与执行速度有关,那么我会做一个真正的C函数,如果你是我可能会建议一个预处理宏。
所以,这样的:
#define Yield0() ((random() & 0xf) == 0 && Yield())
选择您要呼叫的百分比机会面具。 对于0xF并如果random()
具有良好的低位随机性,那么你会看到1个产量()在16个电话。 如果你能使用MT或其他高品质的随机数发生器,将低阶位将直接有用的,否则你可能想random() >> 3 & ...
而你只需要投入Yield0()调用无处不在。
我定义一个函数是这样的:
void maybe_yield() {
if (rand() & 0x10)
yield();
}
然后撒上调用maybe_yield()
在你的代码。 根据你想要多久屈服于被调用,您可以更改0x10
一个常数设置,以获得更多的比特yield()
称为更频繁。 除此之外,一定要调用srand()
与从一个运行到下一个改变以在不同的运行得到不同序列的值。
选项A:为什么不叫yield()
当线程卡住? 更好的是,为什么不封装在其中可能会卡住每一个操作:
int disk_read (...) { begin_io (); while (!io_completed && !timed_out()) yield(); if (timed_out()) // etc. ... }
选项B:一般-与合作产生-当另一个线程没有准备好运行, yield()
是一个空操作。 因此,把它无处不在:
void thread1 (...) { yield(); do_something_a(); yield(); do_something_b(); yield(); do_something_c(); ... }
选项C:信托是处理器足够快,并等待事情经常发生,以至于最低yields()
工作得很好:
void thread1 (...) { init(); while (...) { do_heavy_crunching(); yield(); do_something_else(); } }
在数以百计的现实世界的应用,选择C的作品就好了。 该决定通常有助于,而不是伤害。
其实,当你在一个协同操作线程环境中运行,你真的想要确定性。
但是,如果你是死心塌地的做下去,你只需要使它随机的。
#include <stdlib.h>
// And make sure you seed the generator with srand() somewhere.
#define YIELD_CHANCE 15
#define yield Yield
#ifdef YIELD_CHANCE
#if YIELD_CHANCE > 0
#if YIELD_CHANCE <= 100
#undef yield
void yield(void) {
if (rand() < (RAND_MAX / (100/YIELD_CHANCE)))
Yield();
}
#endif
#endif
#endif
然后改变你的Yield
要求,以yield
取决于什么价值, YIELD_CHANCE
被设定为在编译的时候,你会得到确定性或不确定性的行为。
如果它不通过100〜1的外部存在或者是, yield
将产生所有的时间。 如果它的范围之内,那么它会调用Yield
随机函数的基础上,你给它的概率。
你说你不想要一个预处理器,但它使得它容易得多。
#!/usr/bin/perl
chomp(my $n =<stdin>);
open (my $f, '<', $n);
while (my $l = <$f>) {
print $l;
if ($l =~ /^[\s][^\.]/) {
$r=rand();
if ( int($r*5) == 1 ) {
print "\tcall Yield\n";
}
}
}
该perl脚本(我第一次)将读取从标准输入一个文件名,并随机插入一个呼叫到一个能够轻易地编译GCC -S生成的程序集。 它可能无法正常工作,是你的编译器/拱,但正则表达式几乎无所不能。
一个很好的补充将是为您的处理器跳转指令前总是加产量。 这样可以节省你的洒。 最后,你可以使用随机调用包装函数跳跃之前()。