OPの質問が理にかなっているのかどうかについての議論に加えて、考えられる解決策は次のとおりです。
スケジュールするスレッドごとにシグナル ハンドラーをインストールします。このハンドラーは say でトリガーされSIGUSR1
、内部的には への呼び出しを呼び出すだけpause()
です。
pause()
スレッド関数はすべて、作成直後にすべてのスレッドを一時停止する への呼び出しで始まります。
を使用して、スケジュールするすべてのスレッドを作成しますpthread_create()
。作成された pthread を配列に格納しpthreads
ます。
(からpthread
)実行する最初の pthread を に割り当てpthread_first
ます。
スケジューリング呼び出しを開始するpthread_kill(pthread_first, SIGUSR2)
には、最初に実行されるスレッドを再開します (pause()
そのブロックをオンにして戻ります)。にpthread_current
なるpthread_first
。
実際にスケジューリングを実行するには、追加のスレッド (おそらくメイン スレッド) が無限にループし、現在のスレッドを中断するためにsleep(SCHEDULING_INTERVALL)
呼び出しpthread_kill(pthread_current, SIGUSR1)
ます (そのシグナル ハンドラーを呼び出し、これを に実行することによりpause()
)。次にpthread_kill(pthread_next, SIGUSR2)
、次のスレッドを再開するために呼び出します (pause()
ブロックをオンにして戻ります)。スレッドの作成中に埋められた配列から、 becomeとpthreat_current
become別のエントリを作成します。pthread_next
pthread_next
pthread
ただし、次のことに注意してください。
シグナルによって中断されて中断されたスレッドpause()
は、共有リソースで何らかの作業を行っている最中に捕捉され、再開されるまでそのままである可能性があるため、互いに足を踏み入れる可能性は非常に高くなります。
他のすべての人へ:はい、私を倒してください;-)
アップデート:
同等の例:
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#define THREADSMAX (3)
#define SCHEDULING_INTERVALL (5) /* seconds */
void
sigusr_handler(int signo)
{
if (SIGUSR1 == signo)
{
pause();
}
}
void *
thread_function(void * pv)
{
intptr_t iThread = (intptr_t) pv;
pause();
{
int i = 0;
for (;;)
{
printf("%d: %d\n", (int) iThread, i++);
sleep(1);
}
}
pthread_exit(NULL);
}
int
main(int argc, char ** argv)
{
struct sigaction signal_action;
memset(&signal_action, 0, sizeof(signal_action));
signal_action.sa_handler = sigusr_handler;
sigemptyset(&signal_action.sa_mask);
sigaction(SIGUSR1, &signal_action, NULL);
sigaction(SIGUSR2, &signal_action, NULL);
{
pthread_t threads[THREADSMAX] =
{ 0 };
intptr_t iThread = 0;
/* create threads */
for (; iThread < THREADSMAX; ++iThread)
{
int iResult = pthread_create(&threads[iThread], NULL, thread_function,
(void *) iThread);
if (iResult)
{
errno = iResult;
perror("pthread_created()");
exit(1);
}
}
sleep(1); /* Unreliable workaround: Try to make sure all threads have started and block in "pause()". See comments on how this might be fixed nicely ... */
/* scheduling loop */
for (iThread = 0;; ++iThread)
{
if (THREADSMAX == iThread)
{
iThread = 0;
}
/* Resume current thread */
{
int iResult = pthread_kill(threads[iThread], SIGUSR2);
if (iResult)
{
errno = iResult;
perror("pthread_kill(..., SIGUSR2)");
exit(2);
}
}
sleep(SCHEDULING_INTERVALL);
/* Suspend current thread */
{
int iResult = pthread_kill(threads[iThread], SIGUSR1);
if (iResult)
{
errno = iResult;
perror("pthread_kill(..., SIGUSR1)");
exit(3);
}
}
}
}
return 0;
}
期待される出力:
0: 0
0: 1
0: 2
0: 3
0: 4
1: 0
1: 1
1: 2
1: 3
1: 4
2: 0
2: 1
2: 2
2: 3
2: 4
0: 5
0: 6
0: 7
0: 8
0: 9
1: 5
1: 6
1: 7
1: 8
1: 9
2: 5
2: 6
...