mirror of
https://github.com/Pithikos/C-Thread-Pool
synced 2024-11-21 21:21:23 +03:00
Merge branch 'master' into gonzus/fix-function-pointer-casts
This commit is contained in:
commit
f8e457b3b4
4
.circleci/Dockerfile
Normal file
4
.circleci/Dockerfile
Normal file
@ -0,0 +1,4 @@
|
||||
FROM ubuntu
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get -y install gcc valgrind time python
|
4
.circleci/README.md
Normal file
4
.circleci/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
Build and push container
|
||||
|
||||
docker build -t pithikos/test-c-thread-pool .
|
||||
docker push pithikos/test-c-thread-pool
|
19
.circleci/config.yml
Normal file
19
.circleci/config.yml
Normal file
@ -0,0 +1,19 @@
|
||||
version: 2.1
|
||||
|
||||
jobs:
|
||||
test:
|
||||
docker:
|
||||
- image: pithikos/test-c-thread-pool
|
||||
steps:
|
||||
- checkout
|
||||
- run:
|
||||
name: Test
|
||||
command: |
|
||||
cd tests/
|
||||
./normal_compile.sh
|
||||
./optimized_compile.sh
|
||||
|
||||
workflows:
|
||||
test:
|
||||
jobs:
|
||||
- test
|
@ -1,4 +1,4 @@
|
||||
![Build status](http://178.62.170.124:3000/pithikos/c-thread-pool/badge/?branch=master)
|
||||
[![CircleCI](https://circleci.com/gh/Pithikos/C-Thread-Pool.svg?style=svg)](https://circleci.com/gh/Pithikos/C-Thread-Pool)
|
||||
|
||||
# C Thread Pool
|
||||
|
||||
|
@ -1,47 +1,47 @@
|
||||
## High level
|
||||
|
||||
|
||||
Description: Library providing a threading pool where you can add work on the fly. The number
|
||||
of threads in the pool is adjustable when creating the pool. In most cases
|
||||
this should equal the number of threads supported by your cpu.
|
||||
|
||||
|
||||
For an example on how to use the threadpool, check the main.c file or just read
|
||||
the documentation found in the README.md file.
|
||||
|
||||
|
||||
In this header file a detailed overview of the functions and the threadpool's logical
|
||||
scheme is presented in case you wish to tweak or alter something.
|
||||
|
||||
|
||||
|
||||
_______________________________________________________
|
||||
scheme is presented in case you wish to tweak or alter something.
|
||||
|
||||
|
||||
|
||||
_______________________________________________________
|
||||
/ \
|
||||
| JOB QUEUE | job1 | job2 | job3 | job4 | .. |
|
||||
| JOB QUEUE | job1 | job2 | job3 | job4 | .. |
|
||||
| |
|
||||
| threadpool | thread1 | thread2 | .. |
|
||||
\_______________________________________________________/
|
||||
|
||||
|
||||
|
||||
|
||||
Description: Jobs are added to the job queue. Once a thread in the pool
|
||||
is idle, it is assigned with the first job from the queue(and
|
||||
erased from the queue). It's each thread's job to read from
|
||||
the queue serially(using lock) and executing each job
|
||||
is idle, it is assigned the first job from the queue (and that job is
|
||||
erased from the queue). It is each thread's job to read from
|
||||
the queue serially (using lock) and executing each job
|
||||
until the queue is empty.
|
||||
|
||||
|
||||
|
||||
|
||||
Scheme:
|
||||
|
||||
thpool______ jobqueue____ ______
|
||||
|
||||
thpool______ jobqueue____ ______
|
||||
| | | | .----------->|_job0_| Newly added job
|
||||
| | | rear ----------' |_job1_|
|
||||
| jobqueue----------------->| | |_job2_|
|
||||
| | | front ----------. |__..__|
|
||||
| | | front ----------. |__..__|
|
||||
|___________| |___________| '----------->|_jobn_| Job for thread to take
|
||||
|
||||
|
||||
job0________
|
||||
|
||||
|
||||
job0________
|
||||
| |
|
||||
| function---->
|
||||
| |
|
||||
| arg------->
|
||||
| | job1________
|
||||
| | job1________
|
||||
| next-------------->| |
|
||||
|___________| | |..
|
||||
|
25
docs/FAQ.md
25
docs/FAQ.md
@ -1,7 +1,7 @@
|
||||
### Why isn't `pthread_exit()` used to exit a thread?
|
||||
|
||||
###Why isn't pthread_exit() used to exit a thread?
|
||||
`thread_do` used to use pthread_exit(). However that resulted in
|
||||
hard times of testing for memory leaks. The reason is that on pthread_exit()
|
||||
`thread_do` used to use `pthread_exit()`. However that resulted in
|
||||
hard times of testing for memory leaks. The reason is that on `pthread_exit()`
|
||||
not all memory is freed bt pthread (probably for future threads or false
|
||||
belief that the application is terminating). For these reasons a simple return
|
||||
is used.
|
||||
@ -9,27 +9,28 @@ is used.
|
||||
Interestingly using `pthread_exit()` results in much more memory being allocated.
|
||||
|
||||
|
||||
###Why do you use sleep() after calling thpool_destroy()?
|
||||
This is needed only in the tests. The reason is that if you call thpool_destroy
|
||||
and then exit immedietely, maybe the program will exit before all the threads
|
||||
### Why do you use `sleep()` after calling `thpool_destroy()`?
|
||||
|
||||
This is needed only in the tests. The reason is that if you call `thpool_destroy()`
|
||||
and then exit immediately, maybe the program will exit before all the threads
|
||||
had the time to deallocate. In that way it is impossible to check for memory
|
||||
leaks.
|
||||
|
||||
In production you don't have to worry about this since if you call exit,
|
||||
immedietely after you destroyied the pool, the threads will be freed
|
||||
anyway by the OS. If you eitherway destroy the pool in the middle of your
|
||||
In production you don't have to worry about this since if you call `exit()`,
|
||||
immediately after you destroyed the pool, the threads will be freed
|
||||
anyway by the OS. If you anyway destroy the pool in the middle of your
|
||||
program it doesn't matter again since the program will not exit immediately
|
||||
and thus threads will have more than enough time to terminate.
|
||||
|
||||
|
||||
### Why does `wait()` use all my CPU?
|
||||
|
||||
###Why does wait() use all my CPU?
|
||||
Notice: As of 11-Dec-2015 wait() doesn't use polling anymore. Instead a conditional variable is being used so in theory there should not be any CPU overhead.
|
||||
Notice: As of 11-Dec-2015 `wait()` doesn't use polling anymore. Instead a conditional variable is being used so in theory there should not be any CPU overhead.
|
||||
|
||||
Normally `wait()` will spike CPU usage to full when called. This is normal as long as it doesn't last for more than 1 second. The reason this happens is that `wait()` goes through various phases of polling (what is called smart polling).
|
||||
|
||||
* Initially there is no interval between polling and hence the 100% use of your CPU.
|
||||
* After that the polling interval grows exponentially.
|
||||
* Finally after x seconds, if there is still work, polling falls back to a very big interval.
|
||||
|
||||
|
||||
The reason `wait()` works in this way, is that the function is mostly used when someone wants to wait for some calculation to finish. So if the calculation is assumed to take a long time then we don't want to poll too often. Still we want to poll fast in case the calculation is a simple one. To solve these two problems, this seemingly awkward behaviour is present.
|
||||
|
17
example.c
17
example.c
@ -13,16 +13,11 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <pthread.h>
|
||||
#include <stdint.h>
|
||||
#include "thpool.h"
|
||||
|
||||
|
||||
void task1(){
|
||||
printf("Thread #%u working on task1\n", (int)pthread_self());
|
||||
}
|
||||
|
||||
|
||||
void task2(){
|
||||
printf("Thread #%u working on task2\n", (int)pthread_self());
|
||||
void task(void *arg){
|
||||
printf("Thread #%u working on %d\n", (int)pthread_self(), (int) arg);
|
||||
}
|
||||
|
||||
|
||||
@ -33,11 +28,11 @@ int main(){
|
||||
|
||||
puts("Adding 40 tasks to threadpool");
|
||||
int i;
|
||||
for (i=0; i<20; i++){
|
||||
thpool_add_work(thpool, task1, NULL);
|
||||
thpool_add_work(thpool, task2, NULL);
|
||||
for (i=0; i<40; i++){
|
||||
thpool_add_work(thpool, task, (void*)(uintptr_t)i);
|
||||
};
|
||||
|
||||
thpool_wait(thpool);
|
||||
puts("Killing threadpool");
|
||||
thpool_destroy(thpool);
|
||||
|
||||
|
@ -62,7 +62,12 @@ test_thread_free 8
|
||||
test_thread_free 1
|
||||
test_thread_free 20
|
||||
test_thread_free_multi 4 20
|
||||
test_thread_free_multi 3 1000
|
||||
test_thread_free_multi 100 100
|
||||
|
||||
# test_thread_free_multi 3 1000 # Takes way too long
|
||||
test_thread_free_multi 3 200
|
||||
|
||||
# test_thread_free_multi 100 100 # Takes way too long
|
||||
test_thread_free_multi 100 20
|
||||
|
||||
|
||||
echo "No memory leaks"
|
||||
|
Loading…
Reference in New Issue
Block a user