mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-05 08:46:02 +02:00

Having a compatibility layer for threading operations, like the one we have for sleep, will allow removing a lot of platform dependent code in the test sources, therefore simplifying the tests themselves. I changed MultiThread.cc and MultiThreadRunControl.cc as examples, but there are other tests files that could benefit from it. I also changed MultiThread.cc to remove all the synchronization based on sleeps. It now works using thread barriers, which should make the tests less prone to random failure (although I don't think these ones were particularly flaky) and run faster (since we don't wait for nothing). The fallouts of that change on the Java part of the tests are taken care of as well. Change-Id: I7be86a5727877638c0ff0a489d263ee6bbe84764 Signed-off-by: Simon Marchi <simon.marchi@polymtl.ca> Reviewed-on: https://git.eclipse.org/r/36814 Reviewed-by: Marc Khouzam <marc.khouzam@ericsson.com> Tested-by: Hudson CI Tested-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com> Reviewed-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
104 lines
2.6 KiB
C++
104 lines
2.6 KiB
C++
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include "Sleep.h"
|
|
#include "Thread.h"
|
|
|
|
static const int NUM_THREADS = 5;
|
|
|
|
struct PrintHelloArgs {
|
|
int thread_id;
|
|
ThreadBarrier *barrier_start;
|
|
ThreadBarrier *barrier_finish;
|
|
ThreadSemaphore *sem_start;
|
|
};
|
|
|
|
static ThreadRet THREAD_CALL_CONV PrintHello(void *void_arg)
|
|
{
|
|
struct PrintHelloArgs *args = (struct PrintHelloArgs *) void_arg;
|
|
int thread_id = args->thread_id;
|
|
ThreadBarrier *barrier_start = args->barrier_start;
|
|
ThreadBarrier *barrier_finish = args->barrier_finish;
|
|
ThreadSemaphore *sem_start = args->sem_start;
|
|
|
|
/* Indicate to main thread that the thread is started. */
|
|
ThreadSemaphorePut(sem_start);
|
|
|
|
printf("Hello World! It's me, thread #%d!\n", thread_id);
|
|
|
|
/* Make sure that all threads are started before the breakpoint in main hits. */
|
|
ThreadBarrierWait(barrier_start);
|
|
|
|
printf("Thread %d in the middle\n", thread_id);
|
|
|
|
/* Make sure that the thread does not finish before the breakpoint in main hits. */
|
|
ThreadBarrierWait(barrier_finish);
|
|
|
|
printf("Goodbye World! From thread #%d\n", thread_id);
|
|
|
|
return THREAD_DEFAULT_RET;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
ThreadHandle threads[NUM_THREADS];
|
|
struct PrintHelloArgs args[NUM_THREADS];
|
|
|
|
/* Used to make rendez-vous points between all threads. */
|
|
ThreadBarrier barrier_start;
|
|
ThreadBarrier barrier_finish;
|
|
|
|
/* Used to tell when a thread is started for real. */
|
|
ThreadSemaphore sem_start;
|
|
|
|
/* + 1 for main thread */
|
|
ThreadBarrierInit(&barrier_start, NUM_THREADS + 1);
|
|
ThreadBarrierInit(&barrier_finish, NUM_THREADS + 1);
|
|
|
|
ThreadSemaphoreInit(&sem_start, 0);
|
|
|
|
for (int t = 0; t < NUM_THREADS; t++)
|
|
{
|
|
printf("In main: creating thread #%d\n", t);
|
|
|
|
args[t].thread_id = t;
|
|
args[t].barrier_start = &barrier_start;
|
|
args[t].barrier_finish = &barrier_finish;
|
|
args[t].sem_start = &sem_start;
|
|
|
|
int ret = StartThread(PrintHello, &args[t], &threads[t]);
|
|
|
|
if (!ret)
|
|
{
|
|
printf("Error: StartThread failed.\n");
|
|
exit(-1);
|
|
}
|
|
|
|
/* Wait until the thread has really started. */
|
|
ThreadSemaphoreTake(&sem_start);
|
|
|
|
printf("In main: thread #%d has started\n", t); /* Breakpoint LINE_MAIN_AFTER_THREAD_START */
|
|
}
|
|
|
|
/* Let the threads continue to the 'critical' section> */
|
|
ThreadBarrierWait(&barrier_start);
|
|
|
|
printf("In main thread, all threads created.\n"); /* main breakpoint here */
|
|
|
|
SLEEP(30);
|
|
|
|
/* Unlock the threads and let the program finish. */
|
|
ThreadBarrierWait(&barrier_finish);
|
|
|
|
for (int t = 0; t < NUM_THREADS; t++)
|
|
{
|
|
printf("In main, joining thread #%d\n", t);
|
|
JoinThread(threads[t], NULL);
|
|
}
|
|
|
|
ThreadBarrierDestroy(&barrier_start);
|
|
ThreadBarrierDestroy(&barrier_finish);
|
|
ThreadSemaphoreDestroy(&sem_start);
|
|
|
|
return 0;
|
|
}
|