|
17 | 17 | */ |
18 | 18 |
|
19 | 19 | #include <iostream> |
| 20 | +#include <string> |
| 21 | + |
| 22 | +// for pipe |
| 23 | +#include <unistd.h> |
| 24 | + |
| 25 | +// for select |
| 26 | +#include <sys/time.h> |
| 27 | +#include <sys/types.h> |
| 28 | +#include <unistd.h> |
| 29 | + |
| 30 | +// for strcpy |
| 31 | +#include <string.h> |
| 32 | + |
| 33 | + |
20 | 34 | #include "threadpool.h" |
21 | 35 |
|
22 | 36 | using namespace std; |
23 | 37 |
|
| 38 | +#define BUFFER_SIZE 1024 |
| 39 | + |
| 40 | +ThreadPool *myPool = NULL; |
| 41 | + |
| 42 | + |
| 43 | +string callee( char* name ){ |
| 44 | + string result; |
| 45 | + |
| 46 | + cout << " callee>> hello world,..." << name << endl; |
| 47 | + |
| 48 | + //sleep( 1 ); |
| 49 | + |
| 50 | + result = result + name + " is a good guy"; |
| 51 | + |
| 52 | + return result; |
| 53 | +} |
24 | 54 |
|
25 | | -#define ITERATIONS 200 |
26 | 55 |
|
27 | 56 | class SampleWorkerThread : public WorkerThread |
28 | 57 | { |
29 | 58 | public: |
30 | | - int id; |
| 59 | + int id; |
| 60 | + string _data; |
| 61 | + int _pipefd[2]; |
31 | 62 |
|
32 | 63 | unsigned virtual executeThis() |
33 | 64 | { |
34 | 65 | // Instead of sleep() we could do anytime consuming work here. |
35 | 66 | //Using ThreadPools is advantageous only when the work to be done is really time consuming. (atleast 1 or 2 seconds) |
36 | | - sleep(2); |
| 67 | + cout << " ->Processing SampleWorkerThread " << id << "\t address=" << this << endl; |
| 68 | + char *param = const_cast<char*>(_data.c_str()); |
| 69 | + string result = callee( param ); |
| 70 | + |
| 71 | + char buf2[BUFFER_SIZE]; |
| 72 | + strcpy( buf2, result.c_str() ); |
| 73 | + |
| 74 | + cout << " writing..." << buf2 << " to pipefd," << _pipefd[1] << endl; |
| 75 | + |
| 76 | + cout << " <-Processing SampleWorkerThread " << id << "\t address=" << this << endl; |
| 77 | + |
| 78 | + write( _pipefd[1], &buf2, strlen( result.c_str() ) ); |
37 | 79 |
|
38 | 80 | return(0); |
39 | 81 | } |
40 | 82 |
|
41 | 83 |
|
42 | | - SampleWorkerThread(int id) : WorkerThread(id), id(id) |
| 84 | + SampleWorkerThread(int id, int pipe_fd_read, int pipe_fd_write, string data ) : WorkerThread(id), id(id) |
43 | 85 | { |
44 | | -// cout << "Creating SampleWorkerThread " << id << "\t address=" << this << endl; |
| 86 | + _pipefd[0] = pipe_fd_read; |
| 87 | + _pipefd[1] = pipe_fd_write; |
| 88 | + _data = data; |
| 89 | + |
| 90 | + cout << " Creating SampleWorkerThread " << id << "\t address=" << this << endl; |
45 | 91 | } |
46 | 92 |
|
47 | 93 | ~SampleWorkerThread() |
48 | 94 | { |
49 | | -// cout << "Deleting SampleWorkerThread " << id << "\t address=" << this << endl; |
| 95 | + cout << " Deleting SampleWorkerThread " << id << "\t address=" << this << endl; |
50 | 96 | } |
51 | 97 | }; |
52 | 98 |
|
53 | 99 |
|
| 100 | +string caller ( const char * name ){ |
| 101 | + |
| 102 | + |
| 103 | + int pipefd[2]; |
| 104 | + |
| 105 | + if (pipe(pipefd) == -1) { |
| 106 | + cout << "Pipe initialize error" << endl; |
| 107 | + return NULL; |
| 108 | + } |
| 109 | + |
| 110 | + SampleWorkerThread* wthr = new SampleWorkerThread( 9999, pipefd[0], pipefd[1], name ); |
| 111 | + |
| 112 | + // 丟給 thread pool 執行 |
| 113 | + myPool->assignWork( wthr ); |
| 114 | + |
| 115 | + |
| 116 | + fd_set rfds; |
| 117 | + struct timeval tv; |
| 118 | + int retval; |
| 119 | + int fd_max; |
| 120 | + |
| 121 | + /* Watch pipefd[1] to see when it has input. */ |
| 122 | + FD_ZERO(&rfds); |
| 123 | + FD_SET( pipefd[0], &rfds); |
| 124 | + |
| 125 | + /* Wait up to five seconds. */ |
| 126 | + tv.tv_sec = 7; |
| 127 | + tv.tv_usec = 0; |
| 128 | + |
| 129 | + fd_max = pipefd[1]+1; |
| 130 | + |
| 131 | + // 用 select 等待回傳 |
| 132 | + cout << "等待回傳中...in 7 sec..." << pipefd[0] << "," << pipefd[1] << "," << fd_max << endl; |
| 133 | + retval = select( fd_max, &rfds, NULL, NULL, &tv); |
| 134 | + /* Don't rely on the value of tv now! */ |
| 135 | + |
| 136 | + |
| 137 | + if( retval > 0 ){ |
| 138 | + cout << "回傳觸發了!!" << endl; |
| 139 | + /* FD_ISSET(0, &rfds) will be true. */ |
| 140 | + |
| 141 | + // 處理回傳值 |
| 142 | + char buf2[BUFFER_SIZE]; |
| 143 | + ssize_t read_bytes = read( pipefd[0], &buf2, BUFFER_SIZE ); // 接 callee 回傳的資料 |
| 144 | + |
| 145 | + cout << " buffer :: " << buf2 << endl; |
| 146 | + |
| 147 | + string result = string( buf2 ); |
| 148 | + |
| 149 | + return result; |
| 150 | + } |
| 151 | + else if ( retval == 0 ){ |
| 152 | + cout << "等不到回傳" << endl; |
| 153 | + // 處理逾期 |
| 154 | + } |
| 155 | + else { |
| 156 | + cout << "等待有錯誤" << endl; |
| 157 | + // 處理例外 |
| 158 | + } |
| 159 | + |
| 160 | + return NULL; |
| 161 | +} |
| 162 | + |
| 163 | + |
| 164 | +static void * thread_start(void *arg) |
| 165 | +{ |
| 166 | + string result = caller( "Mat multi-threads" ); |
| 167 | + cout << "MT:>>>" << result << "<<<" << endl; |
| 168 | +} |
| 169 | + |
| 170 | + |
| 171 | + |
54 | 172 | int main(int argc, char **argv) |
55 | 173 | { |
56 | | - //ThreadPool(N); |
57 | | - //Create a Threadpool with N number of threads |
58 | | - ThreadPool* myPool = new ThreadPool(25); |
| 174 | + myPool = new ThreadPool(1); // single thread; |
| 175 | + //myPool = new ThreadPool(5); // multi thread; |
59 | 176 | myPool->initializeThreads(); |
60 | 177 |
|
61 | 178 | //We will count time elapsed after initializeThreads() |
62 | 179 | time_t t1=time(NULL); |
63 | 180 |
|
64 | | - //Lets start bullying ThreadPool with tonnes of work !!! |
65 | | - for(unsigned int i=0;i<ITERATIONS;i++){ |
66 | | - SampleWorkerThread* myThread = new SampleWorkerThread(i); |
67 | | -//cout << "myThread[" << myThread->id << "] = [" << myThread << "]" << endl; |
68 | | - myPool->assignWork(myThread); |
69 | | - } |
| 181 | + pthread_t thread_id; |
| 182 | + pthread_create( &thread_id, NULL, &thread_start,NULL); |
| 183 | + pthread_create( &thread_id, NULL, &thread_start,NULL); |
| 184 | + pthread_create( &thread_id, NULL, &thread_start,NULL); |
| 185 | + pthread_create( &thread_id, NULL, &thread_start,NULL); |
| 186 | + pthread_create( &thread_id, NULL, &thread_start,NULL); |
| 187 | + pthread_create( &thread_id, NULL, &thread_start,NULL); |
| 188 | + pthread_create( &thread_id, NULL, &thread_start,NULL); |
| 189 | + pthread_create( &thread_id, NULL, &thread_start,NULL); |
| 190 | + |
| 191 | + |
| 192 | + string result = caller( "Mat" ); |
| 193 | + cout << ">>>" << result << "<<<" << endl; |
| 194 | + |
| 195 | + string result1 = caller( "Matt" ); |
| 196 | + cout << ">>>" << result1 << "<<<" << endl; |
| 197 | + |
| 198 | + string result2 = caller( "Matttt" ); |
| 199 | + cout << ">>>" << result2 << "<<<" << endl; |
| 200 | + |
| 201 | + string result3 = caller( "Mattttttt" ); |
| 202 | + cout << ">>>" << result3 << "<<<" << endl; |
70 | 203 |
|
| 204 | + time_t t2=time(NULL); |
| 205 | + |
| 206 | + |
| 207 | + // 注意,切換不同的 Worker thread 數,可以看到時間上的差異 |
| 208 | + cout << t2-t1 << " seconds elapsed\n" << endl; |
| 209 | + |
| 210 | + //sleep( 3 ); |
71 | 211 | // destroyPool(int maxPollSecs) |
72 | 212 | // Before actually destroying the ThreadPool, this function checks if all the pending work is completed. |
73 | 213 | // If the work is still not done, then it will check again after maxPollSecs |
74 | 214 | // The default value for maxPollSecs is 2 seconds. |
75 | 215 | // And ofcourse the user is supposed to adjust it for his needs. |
76 | | - |
77 | | - myPool->destroyPool(2); |
| 216 | + myPool->destroyPool(2); |
78 | 217 |
|
79 | | - time_t t2=time(NULL); |
80 | | - cout << t2-t1 << " seconds elapsed\n" << endl; |
81 | 218 | delete myPool; |
82 | 219 |
|
83 | 220 | return 0; |
|
0 commit comments