Skip to content

Commit ca7f7b1

Browse files
committed
add example
1 parent b245648 commit ca7f7b1

File tree

4 files changed

+275
-1
lines changed

4 files changed

+275
-1
lines changed

snippet/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ endforeach()
1717
# Run add_subdirectory() for each
1818

1919
foreach (SUB_DIR ${SUB_DIRS})
20-
message ("-- [LarkSDK] Building snippet: ${SUB_DIR}")
20+
message ("-- Building snippet: ${SUB_DIR}")
2121
add_subdirectory (${SUB_DIR})
2222

2323
endforeach()

snippet/ExampleDemo/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
add_executable (ExampleDemo main.cpp)

snippet/ExampleDemo/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# ExampleDemo
2+
3+
网上找的一个实例程序,可以参考。不一定直接符合题目要求。
4+
5+
个人想做跨平台,也就是用 C++ 11 的标准库实现,不深入到系统 API 的层面。
6+
7+
此演示程序请在 Linux 下运行。
8+

snippet/ExampleDemo/main.cpp

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <unistd.h>
4+
#include <sys/types.h>
5+
#include <pthread.h>
6+
#include <assert.h>
7+
#include <iostream>
8+
9+
10+
#define num 100
11+
#define thread_num 3
12+
13+
14+
int data[num]; // 待排序数据
15+
int thread_unit = 10; // 每个任务处理10个数据
16+
17+
18+
typedef struct worker
19+
{
20+
void *(*process)(void *arg); /*该任务需要调用的函数*/
21+
void *arg; /*该任务需要的参数*/
22+
struct worker *next;
23+
} task;
24+
25+
26+
/*线程池结构*/
27+
typedef struct
28+
{
29+
pthread_mutex_t queue_lock; // 线程池的互斥变量
30+
pthread_cond_t queue_ready; // 线程池的条件变量
31+
task *queue_head; /*链表结构,线程池中所有等待任务*/
32+
int shutdown; /*是否销毁线程池*/
33+
pthread_t *threadid; // 线程ID的指针
34+
int max_thread_num; /*线程池中允许的活动线程数目*/
35+
int cur_queue_size; /*当前等待队列的任务数目*/
36+
} thread_pool;
37+
38+
39+
int add_task(void *(*process)(void *arg), void *arg);
40+
void *thread_routine(void *arg);
41+
42+
43+
static thread_pool *pool = NULL; // 刚开始指针为空
44+
45+
46+
void pool_init(int max_thread_num)
47+
{
48+
pool = (thread_pool *)malloc(sizeof(thread_pool));
49+
pthread_mutex_init(&(pool->queue_lock), NULL);
50+
pthread_cond_init(&(pool->queue_ready), NULL);
51+
pool->queue_head = NULL;
52+
pool->max_thread_num = max_thread_num;
53+
pool->cur_queue_size = 0;
54+
pool->shutdown = 0;
55+
pool->threadid = (pthread_t *)malloc(max_thread_num * sizeof(pthread_t));
56+
int i = 0;
57+
for (i = 0; i < max_thread_num; i++)
58+
{
59+
pthread_create(&(pool->threadid[i]), NULL, thread_routine, NULL); // 创建线程
60+
}
61+
}
62+
63+
int add_task(void *(*process)(void *arg), void *arg)
64+
{ /*向线程池中加入任务*/
65+
task *newworker = (task *)malloc(sizeof(task)); /*构造一个新任务*/
66+
newworker->process = process;
67+
newworker->arg = arg;
68+
newworker->next = NULL;
69+
pthread_mutex_lock(&(pool->queue_lock)); // 向任务队列中添加任务是互斥操作要上锁
70+
task *member = pool->queue_head;
71+
if (member != NULL)
72+
{
73+
while (member->next != NULL)
74+
member = member->next;
75+
member->next = newworker;
76+
}
77+
else
78+
{
79+
pool->queue_head = newworker; // 尾插法
80+
}
81+
assert(pool->queue_head != NULL);
82+
pool->cur_queue_size++;
83+
pthread_mutex_unlock(&(pool->queue_lock));
84+
pthread_cond_signal(&(pool->queue_ready)); /*条件已满足,向等待这个条件的线程发出信号,唤醒休眠的进程*/
85+
return 0;
86+
}
87+
88+
int pool_destroy()
89+
{
90+
if (pool->shutdown) return -1; /*防止两次调用*/
91+
pool->shutdown = 1;
92+
/*唤醒所有等待线程,线程池要销毁了*/
93+
pthread_cond_broadcast(&(pool->queue_ready));
94+
int i;
95+
for (i = 0; i < pool->max_thread_num; i++) pthread_join(pool->threadid[i], NULL); // 所有线程结束
96+
free(pool->threadid);
97+
/*销毁等待队列*/
98+
task *head = NULL;
99+
while (pool->queue_head != NULL)
100+
{
101+
head = pool->queue_head;
102+
pool->queue_head = pool->queue_head->next;
103+
free(head);
104+
}
105+
/*条件变量和互斥量也别忘了销毁*/
106+
pthread_mutex_destroy(&(pool->queue_lock));
107+
pthread_cond_destroy(&(pool->queue_ready));
108+
free(pool);
109+
/*销毁后指针置空是个好习惯*/
110+
pool = NULL;
111+
return 0;
112+
}
113+
114+
void *thread_routine(void *arg)
115+
{
116+
printf("starting thread 0x%lx\n", pthread_self());
117+
while (1)
118+
{
119+
pthread_mutex_lock(&(pool->queue_lock));
120+
while (pool->cur_queue_size == 0 && !pool->shutdown)
121+
{ /*如果等待队列为0并且不销毁线程池,则处于阻塞状态; 注意pthread_cond_wait是一个原子操作,等待前会解锁,唤醒后会加锁*/
122+
printf("thread 0x%lx is waiting\n", pthread_self());
123+
pthread_cond_wait(&(pool->queue_ready), &(pool->queue_lock)); // 线程进行等待状态,同时解锁
124+
}
125+
/*线程池要销毁了*/
126+
if (pool->shutdown)
127+
{
128+
/*遇到break,continue,return等跳转语句,千万不要忘记先解锁*/
129+
pthread_mutex_unlock(&(pool->queue_lock));
130+
printf("thread 0x%lx will exit\n", pthread_self());
131+
pthread_exit(NULL);
132+
}
133+
printf("thread 0x%lx is starting to work\n", pthread_self());
134+
assert(pool->cur_queue_size != 0); // 任务队列不为空
135+
assert(pool->queue_head != NULL); //
136+
/*等待队列长度减去1,并取出链表中的头元素*/
137+
pool->cur_queue_size--;
138+
task *worker = pool->queue_head;
139+
pool->queue_head = worker->next;
140+
pthread_mutex_unlock(&(pool->queue_lock));
141+
(*(worker->process))(worker->arg); /*调用排序函数函数开始执行任务*/
142+
free(worker);
143+
worker = NULL;
144+
sleep(1);
145+
}
146+
std::cout << "excute here!" << std::endl;
147+
pthread_exit(NULL);
148+
}
149+
150+
void heapsort(int begin)
151+
{ // 将每一段进行排序
152+
int start = begin * thread_unit;
153+
int end = begin * thread_unit + thread_unit - 1; // 最后一个元素
154+
int min, temp;
155+
for (int i = start; i <= end; i++)
156+
{
157+
min = i;
158+
for (int j = i; j <= end; j++)
159+
{
160+
if (data[min] > data[j]) min = j;
161+
}
162+
if (i != min)
163+
{ // 交换
164+
data[i] = data[i] + data[min];
165+
data[min] = data[i] - data[min];
166+
data[i] = data[i] - data[min];
167+
}
168+
}
169+
}
170+
171+
void *myprocess(void *arg)
172+
{
173+
printf("threadid is 0x%lx, working on data %d\n", pthread_self(), *((int *)arg));
174+
int start = *((int *)arg); // 排序开始的地方
175+
heapsort(start);
176+
return NULL;
177+
}
178+
179+
void *merge(void *)
180+
{ // k路归并排序
181+
int *start = (int *)malloc(10 * sizeof(int));
182+
int *top = (int *)malloc(10 * sizeof(int));
183+
int *temp = (int *)malloc(num * sizeof(int));
184+
for (int i = 0; i < 10; i++)
185+
{
186+
start[i] = i * 10;
187+
top[i] = 10 * (i + 1);
188+
}
189+
int count = 0; // temp数组的起始位置
190+
// 开始归并
191+
int mark, minimum, flag;
192+
while (count != num)
193+
{
194+
flag = 0;
195+
for (int i = 0; i < 10; i++)
196+
{
197+
if (start[i] < top[i])
198+
{ // 没有超出界限
199+
if (flag == 0)
200+
{ // 只执行1次
201+
minimum = start[i];
202+
mark = i; // i标示属于那一段
203+
}
204+
flag = 1;
205+
if (data[minimum] > data[start[i]])
206+
{
207+
minimum = start[i];
208+
mark = i;
209+
}
210+
}
211+
}
212+
start[mark]++;
213+
temp[count++] = data[minimum];
214+
}
215+
for (int i = 0; i < num; i++) data[i] = temp[i];
216+
free(start);
217+
free(top);
218+
free(temp);
219+
return NULL;
220+
}
221+
222+
223+
int main(int argc, char **argv)
224+
{
225+
for (int j = 0; j < num; j++)
226+
{
227+
data[j] = rand() % 100;
228+
if (j != 0 && j % thread_unit == 0) std::cout << std::endl;
229+
std::cout << data[j] << " ";
230+
}
231+
std::cout << std::endl;
232+
pool_init(thread_num); /*线程池中最多3个活动线程*/
233+
sleep(1);
234+
/*连续向任务队列中投入10个任务*/
235+
int *workingnum = (int *)malloc(sizeof(int) * 10);
236+
int i;
237+
for (i = 0; i < 10; i++)
238+
{
239+
workingnum[i] = i;
240+
add_task(myprocess, &workingnum[i]);
241+
}
242+
sleep(1); // 等待前面10个任务完成
243+
std::cout << "after sorting:" << std::endl;
244+
for (int j = 0; j < num; j++)
245+
{
246+
if (j != 0 && j % thread_unit == 0) std::cout << std::endl;
247+
std::cout << data[j] << " ";
248+
}
249+
add_task(merge, NULL); // 最后的数据排序
250+
/*等待所有任务完成*/
251+
sleep(20);
252+
/*销毁线程池*/
253+
pool_destroy();
254+
std::cout << "after merging:" << std::endl;
255+
for (int j = 0; j < num; j++)
256+
{
257+
if (j != 0 && j % thread_unit == 0) std::cout << std::endl;
258+
std::cout << data[j] << " ";
259+
}
260+
std::cout << std::endl;
261+
free(workingnum);
262+
263+
264+
return 0;
265+
}

0 commit comments

Comments
 (0)