Before the POSIX standard, each computer vendor would implement its own thread library and the resulting programs were not protable across different computer systems.
#include <pthread.h> |
cc -mt [other flags] file... -lpthread [other libraries] |
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void*), void *arg); |
Parameters:
See next item for more details
The function can have one parameter (passed by reference) and can return a value (the value must be an address of some variable)
Remember that you must pass the address !!!
Return value:
The following definition will define one such variable; and the name of our variable is "attr" (you can call the variable any name that you like):
pthread_attr_t attr; |
pthread_attr_init(&attr); |
| Attribute | Default | Meaning of default |
|---|---|---|
| contentionscope | PTHREAD_SCOPE_PROCESS | Thread will compete for resources within the process |
| detachstate | PTHREAD_CREATE_JOINABLE | Thread is joinable by other threads |
| stackaddr | NULL | Workspace (stack) used by thread is allocated (reserved) by the operating system |
| stacksize | NULL | Workspace size used by thread is determined by the operating system |
| priority | 0 | Priority of the thread (the lower the priority value, the higher the priority...) |
| policy | SCHED_OTHER | The scheduling policy is determined by the system |
| inheritsched | PTHREAD_EXPLICIT_SCHED | scheduling policy and parameters are not inherited but explicitly defined by the attribute object |
| guardsize | PAGESIZE | size of guard area for a thread's created stack (this area will help determine if the thread has exceeded the total amount of space that was allocated for the thread) |
(In fact, my examples always use the default values)
|
The stack is used to store:
|
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); |
Example:
pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setstacksize(&attr, 10000000); // 10000000 bytes stack |
The waiting on other threads is accomplished by using the function pthread_join() (more later).
pthread_t TID; /* Thread ID - used for signaling */
pthread_attr_t attr; /* Thread attribute values for creation */
int param;
/* ---------------------------------------------------
Clear out thread attributes (use default values)
--------------------------------------------------- */
if (pthread_attr_init(&attr) != 0)
{ perror("Problem: pthread_attr_init");
exit(1);
}
/* ---------------------------------------------------------
Optionally, set thread attributes if needed (often not)
--------------------------------------------------------- */
if ( pthread_attr_setstacksize(&attr, 10000000) != 0)
{ perror("Problem: pthread_attr_setstacksize");
exit(1);
}
param = some value....;
/* --------------------------------------------------------------
Create thread (once created, thread starts running my_proc()
-------------------------------------------------------------- */
if (pthread_create(&TID, &attr, my_proc, ¶m) != 0)
{ perror("Problem: pthread_create");
exit(1);
}
|
We must also provide a function for the thread to execute:
void *my_proc((void *) x) <---- new thread will begin
{ execution with this function
....
}
|
Multiple parameters:
|
/* --------------------------------------------------------
Worker thread will receive an INTEGER input parameter
-------------------------------------------------------- */
void *worker(void *arg)
{
int *p; // Pointer (reference, address) to an integer variable
int x; // An integer variable
p = (int *) arg; // Casting "(void *)" type to "(int *)"
x = *p
cout << "Hi, my input parameter is " << x << endl;
return(NULL); /* Thread exits (dies) */
}
|
/* --------------------------------------------------------
Main creates thread and passes param to new thread
-------------------------------------------------------- */
int main(int argc, char *argv[])
{
pthread_attr_t attr;
pthread_t tid;
int param; // Integer
pthread_attr_init(&attr);
param = 12345;
pthread_create(&tid[i], &attr, worker, ¶m)
}
|
|
Thread A invokes:
pthread_join(B, &status);
B = ID of a thread
status = variable to receive the exit state of thread.
|
The thread B completes if the function (that thread B executes) returns or thread B executes the pthread_exit() function
Example:
int main(int argc, char *argv[])
{
int i, num_threads;
thread_t tid[100]; /* Thread ID used for thread_join() */
int param[100]; /* used to store parameters for threads */
pthread_attr_t attr;
pthread_attr_init(&attr);
/* -----
Check command line
----- */
if ( argc != 2 )
{
cout << "Usage: " << argv[0] << " Num_Threads" << endl;
exit(1);
}
/* -----
Get number of intervals and number of threads
----- */
num_threads = atoi(argv[1]);
/* ------
Create threads
------ */
for (i = 0; i < num_threads; i = i + 1)
{
param[i] = 1001 + i;
if ( pthread_create(&tid[i], &attr, worker, ¶m[i]) != 0 )
{
cout << "Cannot create thread" << endl;
exit(1);
}
}
/* ----------------------------------
Wait for ALL threads to finish
---------------------------------- */
for (i = 0; i < num_threads; i = i + 1)
pthread_join(tid[i], NULL);
}
|
(See example program above (thread04.C))