[Prev] [Contents] [Next]

C++ destructors and thread termination

Unlike some other threads implementations, C++ destructors for automatic objects will be allowed to run in a well defined and consistent manner when a thread is terminated.

Some things that can cause thread termination are:

In the cases of thread termination, the following occurs, in order.

If a Pthread is terminated using a non-Pthread method (an AS/400 exception, a different thread termination primitive provided by the system, exit() or abort(), or other job termination method), Pthread cancelation cleanup handlers and data destructors do not run.

Example

#define _MULTI_THREADED
#include <stdio.h>
#include <qp0z1170.h>
#include <time.h>
#include <pthread.h>
#include "check.h"

#define bufferSize 100
#define threadRc   55

pthread_key_t   tlskey;

void dataDestructor(void *parm);
void cancelHandler(void *parm);
void *threadfunc(void *parm);
void level2(void);
void level3(void);


class A {
public:
  A(char *label);
  ~A();
private:
  pthread_id_np_t       tid;
  char                  buffer[bufferSize];
};


void dataDestructor(void *parm) {
  printf("In data destructor\n");
  pthread_setspecific(tlskey, NULL);
}

void cancelHandler(void *parm) {
  printf("In cancelation cleanup handler\n");
}

void *threadfunc(void *parm) {
  A             object("start routine object");
  level2();
  return NULL;
}

void level2(void) {
  A             object("Second level object");
  level3();
}

void level3(void) {
  int               rc;
  struct timespec   ts = {5, 0};
  A             object("Third level object");

  pthread_setspecific(tlskey, &tlskey);
  pthread_cleanup_push(cancelHandler, NULL);
  printf("Thread blocked\n");
  rc = pthread_delay_np(&ts);
  if (rc != 0) {
    printf("pthread_delay_np() - return code %d\n", rc);
    return;
  }
  printf("Calling pthread_exit()\n");
  pthread_exit(__VOID(threadRc));
  pthread_cleanup_pop(0);
}

int main(int argc, char **argv)
{
  int                   rc=0;
  int                   i;
  pthread_t             threadid;
  void                 *status;
  int                   fail=0;

  printf("Enter Testcase - %s\n", argv[0]);
  rc = pthread_key_create(&tlskey, dataDestructor);
  checkResults("pthread_key_create()\n", rc);

  printf("----------- Start pthread_cancel() example -------------\n");
  printf("Create a thread\n");
  rc = pthread_create(&threadid, NULL, threadfunc, NULL);
  checkResults("pthread_create()\n", rc);

  sleep(2);
  rc = pthread_cancel(threadid);
  checkResults("pthread_cancel()\n", rc);

  rc = pthread_join(threadid, &status);
  checkResults("pthread_join()\n", rc);
  if (status != PTHREAD_CANCELED) {
    printf("Canceled thread didn't return the expected results\n");
    fail = 1;
  }

  printf("----------- Start pthread_exit() example -------------\n");
  printf("Create a thread\n");
  rc = pthread_create(&threadid, NULL, threadfunc, NULL);
  checkResults("pthread_create()\n", rc);

  rc = pthread_join(threadid, &status);
  checkResults("pthread_join()\n", rc);
  if (__INT(status) != threadRc) {
    printf("pthread_exit() thread didn't return the expected results\n");
    fail = 1;
  }

  pthread_key_delete(tlskey);
  if (fail) {
    printf("At least one thread failed!\n");
    exit(1);
  }
  printf("Main completed\n");
  return 0;
}

A::A(char *label) {
  strncpy(buffer, label, bufferSize);
  pthread_t             me;
  me = pthread_self();
  pthread_getunique_np(&me, &tid);
  printf("`%s' instantiated in thread 0x%.8x %.8x\n",
         buffer, tid);
}
A::~A() {
  printf("`%s' destroyed in thread 0x%.8x %.8x\n",
         buffer, tid);
}

Output

Enter Testcase - QP0WTEST/TPCPP0
----------- Start pthread_cancel() example -------------
Create a thread
`start routine object' instantiated in thread 0x00000000 00000161
`Second level object' instantiated in thread 0x00000000 00000161
`Third level object' instantiated in thread 0x00000000 00000161
Thread blocked
In cancelation cleanup handler
In data destructor
`Third level object' destroyed in thread 0x00000000 00000161
`Second level object' destroyed in thread 0x00000000 00000161
`start routine object' destroyed in thread 0x00000000 00000161
----------- Start pthread_exit() example -------------
Create a thread
`start routine object' instantiated in thread 0x00000000 00000162
`Second level object' instantiated in thread 0x00000000 00000162
`Third level object' instantiated in thread 0x00000000 00000162
Thread blocked
Calling pthread_exit()
In cancelation cleanup handler
In data destructor
`Third level object' destroyed in thread 0x00000000 00000162
`Second level object' destroyed in thread 0x00000000 00000162
`start routine object' destroyed in thread 0x00000000 00000162
Main completed




[Prev] [Contents] [Next]
Copyright © 1998, IBM Corporation. All rights reserved.
Comments? Contact
rchthrds@us.ibm.com