rootiteam/snooze

使用 pthreads 扩展的代码的线程通知管理库

0.4.2 2023-07-03 20:24 UTC

This package is auto-updated.

Last update: 2024-09-03 23:09:47 UTC


README

使用 pthreads 扩展的代码的事件驱动线程通知管理库

用例

ext-pthreads 目前不能方便地对来自多个线程的通知同时执行 wait()。这个库允许您使用 SleeperHandler 来实现这一点。

每个线程必须接收自己的 SleeperNotifier(由于它们是线程安全的,您可以在线程之间共享通知器,但推荐不要这样做)。线程应在其 SleeperNotifier 上调用 wakeupSleeper(),这将导致在 SleeperHandler 上等待的线程被唤醒并处理传递的通知。

它与在数组套接字或文件描述符上使用 select() 系统调用类似,但使用的是线程。

示例

class SleepyThread extends \Thread{
	/** @var \pocketmine\snooze\SleeperNotifier */
	private $notifier;
	/** @var \Threaded */
	private $buffer;

	public function __construct(\pocketmine\snooze\SleeperNotifier $notifier, \Threaded $buffer){
		$this->notifier = $notifier;
		$this->buffer = $buffer;
	}

	public function run() : void{
		$stdin = fopen('php://stdin', 'r');
		while(true){
			echo "Type something and press ENTER:\n";
			//do whatever you're doing
			$line = fgets($stdin); //blocks until the user enters something

			//add the line to the buffer
			$this->buffer[] = $line;

			//send a notification to the main thread to tell it that we read a line
			//the parent thread doesn't have to be sleeping to receive this, it'll process it next time it tries to go
			//back to sleep
			//if the parent thread is sleeping, it'll be woken up to process notifications immediately.
			$this->notifier->wakeupSleeper();
		}
	}
}

$sleeper = new \pocketmine\snooze\SleeperHandler();

$notifier = new \pocketmine\snooze\SleeperNotifier();
$buffer = new \Threaded();
$thread = new SleepyThread($notifier, $buffer);
$sleeper->addNotifier($notifier, function() use($buffer) : void{
	//do some things when this notifier sends a notification
	echo "Main thread got line: " . $buffer->shift();
});

//don't start the thread until we add the notifier, otherwise we could get unexpected behaviour (race conditions)
$thread->start();

while(true){
	$start = microtime(true);
	//do some work that you do every tick

	//process any pending notifications, then try to sleep 50ms until the next tick
	//this may wakeup at any time to process received notifications
	//if it wakes up and there is still time left to sleep before the specified time, it will go back to sleep again
	//until that time, guaranteeing a delay of at least this amount
	//if there are notifications waiting when this is called, they'll be processed before going to sleep
	$sleeper->sleepUntil($start + 0.05);
}

while(true){
	//alternatively, if you want to only wait for notifications and not tick:
	//but from the pthreads rulebook, only ever wait FOR something!
	//this will wait indefinitely until something wakes it up, and then return immediately
	$sleeper->sleepUntilNotification();
}