Skip to content

Commit

Permalink
chore(tests): add more tests
Browse files Browse the repository at this point in the history
Modules:
stack, thread_pool
  • Loading branch information
Water-Melon committed May 5, 2024
1 parent 33010af commit db89f17
Show file tree
Hide file tree
Showing 6 changed files with 197 additions and 2 deletions.
46 changes: 46 additions & 0 deletions docs/book/cn/stack.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,49 @@ typedef int (*stack_iterate_handler)(void *, void *);
- `mln_stack_iterate`:全部遍历完则返回`0`,否则返回`-1`
- `stack_iterate_handler`:若想中断遍历则返回`小于0`的值,否则返回值`大于等于0`


### 示例

```c
#include "mln_stack.h"
#include <stdlib.h>
#include <assert.h>

typedef struct {
void *data1;
void *data2;
} data_t;

static void *copy(data_t *d, void *data)
{
data_t *dup;
assert((dup = (data_t *)malloc(sizeof(data_t))) != NULL);
*dup = *d;
return dup;
}

int main(void)
{
int i;
data_t *d;
mln_stack_t *st1, *st2;

assert((st1 = mln_stack_init((stack_free)free, (stack_copy)copy)) != NULL);

for (i = 0; i < 3; ++i) {
assert((d = (data_t *)malloc(sizeof(data_t))) != NULL);
assert(mln_stack_push(st1, d) == 0);
}

assert((st2 = mln_stack_dup(st1, NULL)) != NULL);

assert((d = mln_stack_pop(st1)) != NULL);
free(d);

mln_stack_destroy(st1);
mln_stack_destroy(st2);

return 0;
}
```
5 changes: 4 additions & 1 deletion docs/book/cn/threadpool.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ typedef void (*mln_thread_data_free)(void *);
- `main_data` 为主线程的用户自定义数据。
- `child_process_handler` 每个子线程的处理函数,该函数有一个参数为主线程下发任务时给出的数据结构指针,返回值为`0`表示处理正常,`非0`表示处理异常,异常时会有日志输出。
- `main_process_handler` 主线程的处理函数,该函数有一个参数为`main_data`,返回值为`0`表示处理正常,`非0`表示处理异常,异常时会有日志输出。**一般情况下,主线程处理函数不应随意自行返回,一旦返回代表线程池处理结束,线程池会被销毁**。
- `free_handler` 为资源释放函数。其资源为主线程下发给子线程的数据结构指针所指向的内容。
- `free_handler` 资源释放函数。其资源为主线程下发给子线程的数据结构指针所指向的内容。注意:这个释放函数仅在子线程退出或线程池销毁时,用于释放尚未被处理或处理完的资源。也就是说,任何经过了`child_process_handler`回调的资源,其释放将完全交由子线程负责,在`child_process_handler`中被释放
- `cond_timeout`为闲置子线程回收定时器,单位为毫秒。当子线程无任务处理,且等待时间超过该定时器时长后,会自行退出。
- `max`线程池允许的最大子线程数量。
- `concurrency`用于`pthread_setconcurrency`设置并行级别参考值,但部分系统并为实现该功能,因此不应该过多依赖该值。在Linux下,该值设为零表示交由本系统实现自行确定并行度。
Expand Down Expand Up @@ -141,6 +141,7 @@ int main(int argc, char *argv[])
static int child_process_handler(void *data)
{
printf("%s\n", (char *)data);
free(data); //data已经被子线程接管,因此子线程的这个回调函数一旦被调用,资源释放就不再由主线程负责了
return 0;
}

Expand All @@ -158,6 +159,8 @@ static int main_process_handler(void *data)
mln_thread_pool_resource_add(text);
usleep(1000);
}

return 0;
}

static void free_handler(void *data)
Expand Down
46 changes: 46 additions & 0 deletions docs/book/en/stack.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,3 +136,49 @@ return value:
- `mln_stack_iterate`: return `0` after all traversal, otherwise return `-1`
- `stack_iterate_handler`: If you want to interrupt the traversal, return the value of `less than 0`, otherwise the return value of `greater than or equal to 0`


### Example

```c
#include "mln_stack.h"
#include <stdlib.h>
#include <assert.h>

typedef struct {
void *data1;
void *data2;
} data_t;

static void *copy(data_t *d, void *data)
{
data_t *dup;
assert((dup = (data_t *)malloc(sizeof(data_t))) != NULL);
*dup = *d;
return dup;
}

int main(void)
{
int i;
data_t *d;
mln_stack_t *st1, *st2;

assert((st1 = mln_stack_init((stack_free)free, (stack_copy)copy)) != NULL);

for (i = 0; i < 3; ++i) {
assert((d = (data_t *)malloc(sizeof(data_t))) != NULL);
assert(mln_stack_push(st1, d) == 0);
}

assert((st2 = mln_stack_dup(st1, NULL)) != NULL);

assert((d = mln_stack_pop(st1)) != NULL);
free(d);

mln_stack_destroy(st1);
mln_stack_destroy(st2);

return 0;
}
```
7 changes: 6 additions & 1 deletion docs/book/en/threadpool.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ The meaning of each member of the parameter structure is as follows:
- `main_data` User-defined data for the main thread.
- `child_process_handler` The processing function of each child thread. This function has a parameter of the data structure pointer given when the main thread sends the task. The return value is `0` to indicate normal processing, and `non-0` to indicate abnormal processing. There will be log output.
- `main_process_handler` The processing function of the main thread, this function has a parameter `main_data`, the return value `0` means normal processing, `non-0` means processing exceptions, and there will be log output when exceptions occur. **Under normal circumstances, the main thread processing function should not return at will. Once the return represents the end of the thread pool processing, the thread pool will be destroyed**.
- `free_handler` is the resource release function. Its resource is the content pointed to by the data structure pointer issued by the main thread to the child thread.
- `free_handler` is the resource release function. Its resource is the content pointed to by the data structure pointer issued by the main thread to the child thread. Note: This release function is only used to release resources that have not been processed or completed when the child thread exits or the thread pool is destroyed. In other words, any resource that has passed the callback of `child_process_handler` will be completely released by the child thread and will be released in `child_process_handler`.
- `cond_timeout` is the idle sub-thread recycling timer, in milliseconds. When the child thread has no task processing and the waiting time exceeds the timer duration, it will exit by itself.
- The maximum number of child threads allowed by the `max` thread pool.
- `concurrency` is used for `pthread_setconcurrency` to set the parallel level reference value, but some systems do not implement this function, so this value should not be relied on too much. Under Linux, setting this value to zero means that the system can determine the degree of parallelism by itself.
Expand Down Expand Up @@ -140,6 +140,9 @@ int main(int argc, char *argv[])
static int child_process_handler(void *data)
{
printf("%s\n", (char *)data);
free(data); //The data has been taken over by the child thread,
//so once this callback function is called,
//the resource release is no longer the responsibility of the main thread.
return 0;
}

Expand All @@ -157,6 +160,8 @@ static int main_process_handler(void *data)
mln_thread_pool_resource_add(text);
usleep(1000);
}

return 0;
}

static void free_handler(void *data)
Expand Down
40 changes: 40 additions & 0 deletions t/stack.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "mln_stack.h"
#include <stdlib.h>
#include <assert.h>

typedef struct {
void *data1;
void *data2;
} data_t;

static void *copy(data_t *d, void *data)
{
data_t *dup;
assert((dup = (data_t *)malloc(sizeof(data_t))) != NULL);
*dup = *d;
return dup;
}

int main(void)
{
int i;
data_t *d;
mln_stack_t *st1, *st2;

assert((st1 = mln_stack_init((stack_free)free, (stack_copy)copy)) != NULL);

for (i = 0; i < 3; ++i) {
assert((d = (data_t *)malloc(sizeof(data_t))) != NULL);
assert(mln_stack_push(st1, d) == 0);
}

assert((st2 = mln_stack_dup(st1, NULL)) != NULL);

assert((d = mln_stack_pop(st1)) != NULL);
free(d);

mln_stack_destroy(st1);
mln_stack_destroy(st2);

return 0;
}
55 changes: 55 additions & 0 deletions t/thread_pool.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "mln_thread_pool.h"

static int main_process_handler(void *data);
static int child_process_handler(void *data);
static void free_handler(void *data);

int main(int argc, char *argv[])
{
struct mln_thread_pool_attr tpattr;

tpattr.main_data = NULL;
tpattr.child_process_handler = child_process_handler;
tpattr.main_process_handler = main_process_handler;
tpattr.free_handler = free_handler;
tpattr.cond_timeout = 1;
tpattr.max = 1;
tpattr.concurrency = 1;
return mln_thread_pool_run(&tpattr);
}

static int child_process_handler(void *data)
{
printf("%s\n", (char *)data);
free(data);
return 0;
}

static int main_process_handler(void *data)
{
int n, i = 0;
char *text;

while (1) {
if ((text = (char *)malloc(16)) == NULL) {
return -1;
}
n = snprintf(text, 15, "hello world");
text[n] = 0;
mln_thread_pool_resource_add(text);
usleep(1000);

if (++i >= 20) break;
}

return 0;
}

static void free_handler(void *data)
{
free(data);
}

0 comments on commit db89f17

Please sign in to comment.