C - Kill branch of threads

Let a multithreaded (pthreads) C program have a tree of (joinable/attached) threads like this:

main
└── th0
    ├── th1
    │   ├── th3
    │   └── th4
    │       ├── th5
    │       └── th6
    └── th2
        ├── th7
        │   └── th9
        └── th8

Any thread 'thX' can have up to 2 child threads.

The tree is dynamic: branches are cut, and new threads are created continuously.

When a condition is met, I would like to kill not a thread, but a branch of threads. That is, if I want to kill th2, I also want all these to be killed: th7, th8 & th9.

What would be the best(most efficient/most readable) way to do this?

What would be the best(most efficient/most readable) way to keep track of the tree?

Now I'm using a _Thread_local variable to keep the name (X) of a thread, another one to keep the name of its parent, and an array of lenght 2 to keep the names of the childs, but that only allows me to kill a child, not grand-childs and so on.

I don't know if it is relevant, but I'm using GNU/Linux and GCC6

PS: I do want to force kill the threads. I don't malloc, so leaking isn't a problem.

PS.2: It's part of a Branch & Bound algorithm; and this is the bound part.

Upvotes: 0

Views: 125

Answers (1)

Rohit Rakshe
Rohit Rakshe

Reputation: 26

See if this works for you. Each "parent" thread can push cleanup routines which will cancel their children. When you want to cancel the subtree, you do a pthread_cancel() on the parent....

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>


void cancel_child(void *ptr)
{
    printf("cancelling child\n");
    pthread_cancel(*((pthread_t *) ptr));
}

void *runner(void *ptr)
{
    pthread_t thr1, thr2;
    long depth;

    depth = (long) ptr;
    if (!(--depth)) return NULL;

    pthread_create(&thr1, NULL, runner, (void *) depth);
    pthread_cleanup_push(cancel_child, (void *) &thr1);

    pthread_create(&thr2, NULL, runner, (void *) depth);
    pthread_cleanup_push(cancel_child, (void *) &thr2);

    if (depth == 2) {
        sleep(1);
        // cancel the subtree
        pthread_cancel(thr1);
        pthread_cancel(thr2);
    }

    sleep(10 - depth);

    pthread_cleanup_pop(0);
    pthread_cleanup_pop(0);
}


int main()
{
    runner((void *) 3);
}

Upvotes: 1

Related Questions