├── LICENSE ├── Makefile ├── README.md ├── demo ├── Makefile ├── demo_all_sort.cc ├── demo_any_sort.cc └── demo_http_server.cc ├── deps ├── gyp.zip ├── hiredis-0.11.0u2.zip └── libuv-0.10.27.zip ├── docs ├── buttondown.css └── index.html ├── extensions ├── http │ ├── Makefile │ └── cocoflow-http.cc ├── redis │ ├── Makefile │ └── cocoflow-redis.cc ├── test │ ├── Makefile │ ├── test_http_get.cc │ ├── test_http_post.cc │ ├── test_redis.cc │ └── test_redis2.cc ├── vc │ ├── cocoflow-extensions.sln │ ├── libccf-http.vcproj │ ├── test_http_get.vcproj │ └── test_http_post.vcproj └── vcbuild.bat ├── include ├── cocoflow-http.h ├── cocoflow-redis.h └── cocoflow.h ├── lib └── chishaxie ├── src ├── Makefile ├── cocoflow-comm.h ├── cocoflow.cc ├── getaddrinfo.cc ├── max_map_count.c ├── max_map_count.h ├── sleep.cc ├── sync.cc ├── tcp.cc ├── tools.cc └── udp.cc ├── test ├── Makefile ├── benchmark_sleep.cc ├── benchmark_tcp.cc ├── benchmark_udp.cc ├── benchmark_udp2.cc ├── simple_rand.h ├── test_getaddrinfo.cc ├── test_primitive.cc ├── test_sleep.cc ├── test_tcp.cc ├── test_tcp2.cc ├── test_tcp3.cc ├── test_udp.cc ├── test_udp2.cc ├── test_udp3.cc ├── uc_benchmark │ ├── Makefile │ ├── switch_diff.cc │ ├── switch_diff_big_stack.cc │ ├── switch_diff_middle_stack.cc │ ├── switch_diff_small_stack.cc │ ├── switch_diff_super_big_stack.cc │ ├── switch_in_ping_pong.cc │ └── switch_new.cc └── unexpected_tcp_timing.cc ├── vc ├── benchmark_sleep.vcproj ├── benchmark_tcp.vcproj ├── benchmark_udp.vcproj ├── benchmark_udp2.vcproj ├── cocoflow.sln ├── demo_all_sort.vcproj ├── demo_any_sort.vcproj ├── demo_http_server.vcproj ├── libccf.vcproj ├── test.bat ├── test_getaddrinfo.vcproj ├── test_primitive.vcproj ├── test_sleep.vcproj ├── test_tcp.vcproj ├── test_tcp2.vcproj ├── test_tcp3.vcproj ├── test_udp.vcproj ├── test_udp2.vcproj ├── test_udp3.vcproj ├── test_x64.bat └── unexpected_tcp_timing.vcproj └── vcbuild.bat /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | LIB = lib/libuv.a lib/libccf.a 2 | DEMO = demo/demo_all_sort demo/demo_any_sort demo/demo_http_server 3 | TEST = test/test_primitive test/test_sleep test/test_udp test/test_udp2 test/test_udp3 test/test_tcp test/test_tcp2 test/test_tcp3 test/benchmark_udp test/benchmark_udp2 test/benchmark_tcp 4 | 5 | top: $(LIB) 6 | all: $(LIB) $(DEMO) $(TEST) 7 | 8 | $(LIB): src/cocoflow.cc include/cocoflow.h 9 | make -C src 10 | 11 | $(DEMO): demo/*.cc 12 | make -C demo 13 | 14 | $(TEST): test/*.cc 15 | make -C test 16 | 17 | .PHONY: clean test del 18 | 19 | clean: 20 | make -C src clean 21 | make -C demo clean 22 | make -C test clean 23 | 24 | test: $(TEST) 25 | make -C test all_test 26 | 27 | del: $(LIB) 28 | cp lib/libuv.a libuv.a 29 | cp lib/libccf.a libccf.a 30 | cp include/cocoflow.h cocoflow.h 31 | rm -rf include/ lib/ src/ demo/ test/ deps/ docs/ extensions/ test/ vc/ Makefile README.md vcbuild.bat 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Concurrency Control Flow 并发流程控制 2 | ======== 3 | 4 | A C++ framework is based on coroutine and libuv, just using **start**, **await**, **all_of**, **any_of** to control flow. 5 | 6 | 一个基于协程和libuv的C++框架,仅通过 **start**、 **await**、 **all_of**、 **any_of** 控制流程。 7 | 8 | * 示例:你需要等待两个udp的recv事件,并且需要设置一个超时时间,则你可以用使用: 9 | 10 | ### 11 | await ( 12 | any_of ( 13 | all_of ( 14 | udp0.recv, 15 | udp1.recv 16 | ), 17 | sleep(x ms) 18 | ) 19 | ) 20 | 21 | ### Documents: [wiki](https://github.com/chishaxie/cocoflow/wiki) 22 | 23 | ### To build: 24 | 25 | Prerequisites (Linux): 26 | 27 | * GCC 4.2 or newer 28 | * Python 2.6 or 2.7 29 | * GNU Make 3.81 or newer 30 | * (All of above is for libuv) 31 | 32 | Linux: 33 | 34 | make 35 | 36 | Prerequisites (Windows): 37 | 38 | * UnZip (You can extract dependencies by other tools) 39 | * Python 2.6 or 2.7 40 | * Visual Studio 2008 or 2010 or 2012 or 2013 41 | 42 | Windows: 43 | 44 | run vcbuild.bat 45 | 46 | ### To run the tests: 47 | 48 | Linux: 49 | 50 | make test 51 | 52 | Windows: 53 | 54 | run vc\test.bat (for Win32) 55 | run vc\test_x64.bat (for Win64) 56 | 57 | ### License 58 | 59 | (The LGPL License) 60 | -------------------------------------------------------------------------------- /demo/Makefile: -------------------------------------------------------------------------------- 1 | C_ARGS = -g -Wall -O2 2 | CX = g++ 3 | 4 | LIB = ../lib/libuv.a ../lib/libccf.a 5 | BIN = demo_all_sort demo_any_sort demo_http_server 6 | 7 | LIB_ARGS = -L../lib -lccf -luv -lpthread -lrt 8 | INC_ARGS = -I../include 9 | 10 | all: $(BIN) 11 | 12 | $(LIB): 13 | make -C ../src/ 14 | 15 | demo_all_sort: demo_all_sort.cc $(LIB) 16 | $(CX) $(C_ARGS) -o $@ demo_all_sort.cc $(LIB_ARGS) $(INC_ARGS) 17 | 18 | demo_any_sort: demo_any_sort.cc $(LIB) 19 | $(CX) $(C_ARGS) -o $@ demo_any_sort.cc $(LIB_ARGS) $(INC_ARGS) 20 | 21 | demo_http_server: demo_http_server.cc $(LIB) 22 | $(CX) $(C_ARGS) -o $@ demo_http_server.cc $(LIB_ARGS) $(INC_ARGS) 23 | 24 | .PHONY: clean 25 | clean: 26 | rm -f $(BIN) 27 | -------------------------------------------------------------------------------- /demo/demo_all_sort.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "cocoflow.h" 4 | 5 | using namespace std; 6 | 7 | #define WAITING_TIME 1000 8 | 9 | class sort_task: public ccf::user_task 10 | { 11 | protected: 12 | int vals[10]; 13 | int num; 14 | bool right; 15 | void show_cur_vals(int compare_a = -1, int compare_b = -1, int _small = -1, int _large = -1) 16 | { 17 | #if defined(_WIN32) || defined(_WIN64) 18 | compare_a = compare_b = _small = _large = -1; 19 | #endif 20 | ccf::sleep waiting(2 * WAITING_TIME); 21 | await(waiting); 22 | if (this->right) cout << " "; 23 | for (int i=0; inum; i++) 24 | { 25 | if (_small == i) cout << "\033[1;31m"; 26 | else if (_large == i) cout << "\033[1;34m"; 27 | else if (compare_a == i || compare_b == i) cout << "\033[1;32m"; 28 | cout << vals[i] << " "; 29 | if (compare_a == i || compare_b == i || _small == i || _large == i) cout << "\033[0m"; 30 | } 31 | cout << endl; 32 | } 33 | void init(bool right) 34 | { 35 | this->right = right; 36 | this->num = 10; 37 | vals[0] = 9; vals[1] = 5; vals[2] = 11; vals[3] = 7; vals[4] = 2; 38 | vals[5] = 21; vals[6] = 8; vals[7] = 4; vals[8] = 15; vals[9] = 9; 39 | } 40 | }; 41 | 42 | class bubble_sort_task: public sort_task 43 | { 44 | void run() 45 | { 46 | this->init(false); 47 | this->show_cur_vals(); 48 | for (int i=0; inum-1; i++) 49 | { 50 | bool change = false; 51 | for (int j=this->num-1; j>=i; j--) 52 | { 53 | this->show_cur_vals(j, j-1); 54 | if (vals[j] < vals[j-1]) 55 | { 56 | int tmp = vals[j]; 57 | vals[j] = vals[j-1]; 58 | vals[j-1] = tmp; 59 | change = true; 60 | this->show_cur_vals(-1, -1, j-1, j); 61 | } 62 | } 63 | if (!change) 64 | break; 65 | } 66 | } 67 | }; 68 | 69 | class select_sort_task: public sort_task 70 | { 71 | void run() 72 | { 73 | ccf::sleep waiting(WAITING_TIME); 74 | await(waiting); 75 | this->init(true); 76 | this->show_cur_vals(); 77 | for (int i=0; inum-1; i++) 78 | { 79 | int min = i; 80 | for (int j=i+1; jnum; j++) 81 | { 82 | this->show_cur_vals(i, j, min); 83 | if (vals[min] > vals[j]) 84 | { 85 | min = j; 86 | this->show_cur_vals(i, j, min); 87 | } 88 | } 89 | if (min != i) 90 | { 91 | int tmp = vals[i]; 92 | vals[i] = vals[min]; 93 | vals[min] = tmp; 94 | this->show_cur_vals(-1, -1, i, min); 95 | } 96 | } 97 | } 98 | }; 99 | 100 | class main_task: public ccf::user_task 101 | { 102 | void run() 103 | { 104 | cout << "BubbleSort (left) SelectSort (right)" << endl; 105 | bubble_sort_task b; 106 | select_sort_task s; 107 | ccf::all_of all(b, s); 108 | await(all); 109 | } 110 | }; 111 | 112 | int main() 113 | { 114 | ccf::event_task::init(100); 115 | ccf::user_task::init(100); 116 | 117 | //ccf::set_debug(stderr); 118 | 119 | main_task tMain; 120 | ccf::cocoflow(tMain); 121 | return 0; 122 | } 123 | -------------------------------------------------------------------------------- /demo/demo_any_sort.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "cocoflow.h" 4 | 5 | using namespace std; 6 | 7 | #define WAITING_TIME 1000 8 | 9 | class sort_task: public ccf::user_task 10 | { 11 | protected: 12 | int vals[10]; 13 | int num; 14 | bool right; 15 | void show_cur_vals(int compare_a = -1, int compare_b = -1, int _small = -1, int _large = -1) 16 | { 17 | #if defined(_WIN32) || defined(_WIN64) 18 | compare_a = compare_b = _small = _large = -1; 19 | #endif 20 | ccf::sleep waiting(2 * WAITING_TIME); 21 | await(waiting); 22 | if (this->right) cout << " "; 23 | for (int i=0; inum; i++) 24 | { 25 | if (_small == i) cout << "\033[1;31m"; 26 | else if (_large == i) cout << "\033[1;34m"; 27 | else if (compare_a == i || compare_b == i) cout << "\033[1;32m"; 28 | cout << vals[i] << " "; 29 | if (compare_a == i || compare_b == i || _small == i || _large == i) cout << "\033[0m"; 30 | } 31 | cout << endl; 32 | } 33 | void init(bool right) 34 | { 35 | this->right = right; 36 | this->num = 10; 37 | vals[0] = 9; vals[1] = 5; vals[2] = 11; vals[3] = 7; vals[4] = 2; 38 | vals[5] = 21; vals[6] = 8; vals[7] = 4; vals[8] = 15; vals[9] = 9; 39 | } 40 | }; 41 | 42 | class bubble_sort_task: public sort_task 43 | { 44 | void run() 45 | { 46 | this->init(false); 47 | this->show_cur_vals(); 48 | for (int i=0; inum-1; i++) 49 | { 50 | bool change = false; 51 | for (int j=this->num-1; j>=i; j--) 52 | { 53 | this->show_cur_vals(j, j-1); 54 | if (vals[j] < vals[j-1]) 55 | { 56 | int tmp = vals[j]; 57 | vals[j] = vals[j-1]; 58 | vals[j-1] = tmp; 59 | change = true; 60 | this->show_cur_vals(-1, -1, j-1, j); 61 | } 62 | } 63 | if (!change) 64 | break; 65 | } 66 | } 67 | void cancel() 68 | { 69 | cout << "BubbleSort is canceled" << endl; 70 | } 71 | }; 72 | 73 | class select_sort_task: public sort_task 74 | { 75 | void run() 76 | { 77 | ccf::sleep waiting(WAITING_TIME); 78 | await(waiting); 79 | this->init(true); 80 | this->show_cur_vals(); 81 | for (int i=0; inum-1; i++) 82 | { 83 | int min = i; 84 | for (int j=i+1; jnum; j++) 85 | { 86 | this->show_cur_vals(i, j, min); 87 | if (vals[min] > vals[j]) 88 | { 89 | min = j; 90 | this->show_cur_vals(i, j, min); 91 | } 92 | } 93 | if (min != i) 94 | { 95 | int tmp = vals[i]; 96 | vals[i] = vals[min]; 97 | vals[min] = tmp; 98 | this->show_cur_vals(-1, -1, i, min); 99 | } 100 | } 101 | } 102 | void cancel() 103 | { 104 | cout << "SelectSort is canceled" << endl; 105 | } 106 | }; 107 | 108 | class main_task: public ccf::user_task 109 | { 110 | void run() 111 | { 112 | cout << "BubbleSort (left) SelectSort (right)" << endl; 113 | bubble_sort_task b; 114 | select_sort_task s; 115 | ccf::any_of any(b, s); 116 | await(any); 117 | } 118 | }; 119 | 120 | int main() 121 | { 122 | ccf::event_task::init(100); 123 | ccf::user_task::init(100); 124 | 125 | //ccf::set_debug(stderr); 126 | 127 | main_task tMain; 128 | ccf::cocoflow(tMain); 129 | return 0; 130 | } 131 | -------------------------------------------------------------------------------- /demo/demo_http_server.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "cocoflow.h" 5 | 6 | using namespace std; 7 | 8 | static int port = 1337; 9 | 10 | typedef ccf::task<7> my_task; 11 | 12 | class http_task: public my_task 13 | { 14 | public: 15 | ccf::tcp::connected http_connection; 16 | private: 17 | void run() 18 | { 19 | int ret; 20 | char req_buf[3072], res_buf[1024]; 21 | size_t req_len = sizeof(req_buf), res_len = 0, tmp; 22 | ccf::tcp::recv_till recv_task(ret, http_connection, req_buf, req_len, "\r\n\r\n", 4); 23 | await(recv_task); 24 | if (ret == ccf::tcp::success) 25 | { 26 | do { 27 | tmp = res_len; 28 | res_len = sprintf(res_buf, "HTTP/1.0 200 OK\r\nServer: cocoflow-http-server\r\nContent-Type: text/plain\r\nContent-Length: %u\r\n\r\n", (unsigned)(req_len + tmp + 36)); 29 | } while(res_len != tmp); 30 | ccf::tcp::send send_task(ret, http_connection, res_buf, res_len, req_buf, req_len, "--------------------------------\r\n\r\n", 36, res_buf, res_len); 31 | await(send_task); 32 | } 33 | } 34 | }; 35 | 36 | class main_task: public my_task 37 | { 38 | void run() 39 | { 40 | ccf::tcp::listening http_server; 41 | if (http_server.bind(ccf::ip_to_addr("0.0.0.0", port)) != 0) 42 | { 43 | perror("Bind socket"); 44 | exit(1); 45 | } 46 | for (;;) 47 | { 48 | int ret; 49 | http_task *new_http_task = new http_task(); 50 | ccf::tcp::accept accept_task(ret, http_server, new_http_task->http_connection); 51 | await(accept_task); 52 | if (ret != ccf::tcp::success) 53 | break; 54 | ccf::start(new_http_task); 55 | } 56 | } 57 | }; 58 | 59 | int main(int argc, char *argv[]) 60 | { 61 | if (argc > 2) 62 | port = atoi(argv[1]); 63 | 64 | my_task::init(1025); 65 | ccf::event_task::init(4); 66 | 67 | main_task my_main; 68 | 69 | ccf::cocoflow(my_main); 70 | 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /deps/gyp.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chishaxie/cocoflow/4c7c0978940b398d972150ee5b0f0ad8530c396f/deps/gyp.zip -------------------------------------------------------------------------------- /deps/hiredis-0.11.0u2.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chishaxie/cocoflow/4c7c0978940b398d972150ee5b0f0ad8530c396f/deps/hiredis-0.11.0u2.zip -------------------------------------------------------------------------------- /deps/libuv-0.10.27.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chishaxie/cocoflow/4c7c0978940b398d972150ee5b0f0ad8530c396f/deps/libuv-0.10.27.zip -------------------------------------------------------------------------------- /docs/buttondown.css: -------------------------------------------------------------------------------- 1 | div#header,header{border-bottom:1px solid #aaa;margin-bottom:0.5em;}.title{text-align:center;}.author,.date{text-align:center;}div#TOC,nav#TOC{border-bottom:1px solid #aaa;margin-bottom:0.5em;}@media print{div#TOC,nav#TOC{display:none;}}h1,h2,h3,h4,h5,h6{font-family:"Helvetica Neue",Helvetica,"Liberation Sans",Calibri,Arial,sans-serif;page-break-after:avoid;}div div,section section{margin-left:2em;}p{}blockquote{font-style:italic;}li{}li > p{margin-top:1em;}ul{}ul li{}ol{}ol li{}hr{}sub{}sup{}em{}em > em{font-style:normal;}strong{}a{text-decoration:none;}@media screen{a:hover{text-decoration:underline;}}@media print{a{color:black;background:transparent;}a[href^="http://"]:after,a[href^="https://"]:after{content:" (" attr(href) ") ";font-size:90%;}}img{vertical-align:middle;}div.figure{margin-left:auto;margin-right:auto;text-align:center;font-style:italic;}p.caption{}pre,code{background-color:#fdf7ee;white-space:pre-wrap;white-space:-moz-pre-wrap !important;white-space:-pre-wrap;white-space:-o-pre-wrap;word-wrap:break-word;}pre{padding:0.5em;border-radius:5px;border:1px solid #aaa;margin-left:0.5em;margin-right:0.5em;}@media screen{pre{white-space:pre;overflow:auto;border:1px dotted #777;}}code{}p > code,li > code{padding-left:2px;padding-right:2px;}li > p code{padding:2px;}span.math{}div.math{}span.LaTeX{}eq{}table{border-collapse:collapse;border-spacing:0;border-bottom:2pt solid #000;border-top:2pt solid #000;margin-left:auto;margin-right:auto;}thead{border-bottom:1pt solid #000;background-color:#eee;}tr.header{}tbody{}tr{}tr.odd:hover,tr.even:hover{background-color:#eee;}tr.odd{}tr.even{}td,th{vertical-align:top;vertical-align:baseline;padding-left:0.5em;padding-right:0.5em;padding-top:0.2em;padding-bottom:0.2em;}th{font-weight:bold;}tfoot{}caption{caption-side:top;border:none;font-size:0.9em;font-style:italic;text-align:center;margin-bottom:0.3em;padding-bottom:0.2em;}dl{border-top:2pt solid black;padding-top:0.5em;border-bottom:2pt solid black;}dt{font-weight:bold;}dd+dt{border-top:1pt solid black;padding-top:0.5em;}dd{margin-bottom:0.5em;}dd+dd{border-top:1px solid black;}a.footnote,a.footnoteRef{font-size:small;vertical-align:text-top;}a[href^="#fnref"],a.reversefootnote{}@media print{a[href^="#fnref"],a.reversefootnote{display:none;}}div.footnotes{}div.footnotes li[id^="fn"]{}@media print{.noprint{display:none;}} -------------------------------------------------------------------------------- /extensions/http/Makefile: -------------------------------------------------------------------------------- 1 | C_ARGS = -g -Wall -O2 2 | CX = g++ 3 | 4 | LIB = ../../lib/libccf-http.a 5 | 6 | INC_ARGS = -I../../include -I../../src -I../../src/uv 7 | 8 | all: $(LIB) 9 | 10 | ../../lib/libccf-http.a: cocoflow-http.o 11 | ar cr $@ $^ 12 | 13 | cocoflow-http.o: cocoflow-http.cc ../../src/cocoflow-comm.h ../../include/cocoflow.h ../../include/cocoflow-http.h ../../src/uv/uv.h 14 | $(CX) $(C_ARGS) -fPIC -c -o $@ cocoflow-http.cc $(INC_ARGS) 15 | 16 | ../../src/uv/uv.h: 17 | make -C ../../src/ 18 | 19 | .PHONY: clean 20 | clean: 21 | rm -f $(LIB) *.o 22 | -------------------------------------------------------------------------------- /extensions/redis/Makefile: -------------------------------------------------------------------------------- 1 | C_ARGS = -g -Wall -O2 2 | CX = g++ 3 | 4 | LIB = ../../lib/libccf-redis.a 5 | 6 | HIREDIS_DEPS=../../deps/hiredis-0.11.0u2 7 | 8 | HIREDIS_OBJ = net.o hiredis.o sds.o async.o 9 | HIREDIS_OBJ_DEPS = $(HIREDIS_DEPS)/net.o $(HIREDIS_DEPS)/hiredis.o $(HIREDIS_DEPS)/sds.o $(HIREDIS_DEPS)/async.o 10 | 11 | INC_ARGS = -I../../include -I../../src -I../../src/uv -I$(HIREDIS_DEPS) 12 | 13 | all: $(LIB) 14 | 15 | ../../lib/libccf-redis.a: $(HIREDIS_OBJ) cocoflow-redis.o 16 | ar cr $@ $^ 17 | 18 | $(HIREDIS_OBJ): $(HIREDIS_OBJ_DEPS) 19 | cp $(HIREDIS_OBJ_DEPS) . 20 | 21 | cocoflow-redis.o: cocoflow-redis.cc ../../src/cocoflow-comm.h ../../include/cocoflow.h ../../include/cocoflow-redis.h ../../src/uv/uv.h 22 | $(CX) $(C_ARGS) -fPIC -c -o $@ cocoflow-redis.cc $(INC_ARGS) 23 | 24 | ../../src/uv/uv.h: 25 | make -C ../../src/ 26 | 27 | $(HIREDIS_OBJ_DEPS): $(HIREDIS_DEPS).zip 28 | @echo "Dependency analysis ..." 29 | @cd ../../deps/; unzip hiredis-0.11.0u2.zip > /dev/null; cd ../extensions/redis/ 30 | @echo "Compiling hiredis ..." 31 | @make -C $(HIREDIS_DEPS) > /dev/null 32 | @echo "Compiled hiredis" 33 | 34 | .PHONY: clean 35 | clean: 36 | rm -f $(LIB) *.o 37 | -------------------------------------------------------------------------------- /extensions/test/Makefile: -------------------------------------------------------------------------------- 1 | C_ARGS = -g -Wall -O2 2 | CX = g++ 3 | 4 | LIB = ../../lib/libuv.a ../../lib/libccf.a 5 | BIN = test_redis test_redis2 test_http_get test_http_post 6 | 7 | LIB_ARGS = -L../../lib -lccf -luv -lpthread -lrt 8 | INC_ARGS = -I../../include 9 | 10 | LIB_REDIS = ../../lib/libccf-redis.a 11 | LIB_REDIS_ARGS = -lccf-redis 12 | 13 | LIB_HTTP = ../../lib/libccf-http.a 14 | LIB_HTTP_ARGS = -lccf-http 15 | 16 | all: $(BIN) 17 | 18 | $(LIB): 19 | make -C ../../src/ 20 | 21 | $(LIB_REDIS): 22 | make -C ../redis/ 23 | 24 | $(LIB_HTTP): 25 | make -C ../http/ 26 | 27 | test_redis: test_redis.cc $(LIB) $(LIB_REDIS) 28 | $(CX) $(C_ARGS) -o $@ test_redis.cc $(LIB_REDIS_ARGS) $(LIB_ARGS) $(INC_ARGS) 29 | test_redis2: test_redis2.cc $(LIB) $(LIB_REDIS) 30 | $(CX) $(C_ARGS) -o $@ test_redis2.cc $(LIB_REDIS_ARGS) $(LIB_ARGS) $(INC_ARGS) 31 | 32 | test_http_get: test_http_get.cc $(LIB) $(LIB_HTTP) 33 | $(CX) $(C_ARGS) -o $@ test_http_get.cc $(LIB_HTTP_ARGS) $(LIB_ARGS) $(INC_ARGS) 34 | test_http_post: test_http_post.cc $(LIB) $(LIB_HTTP) 35 | $(CX) $(C_ARGS) -o $@ test_http_post.cc $(LIB_HTTP_ARGS) $(LIB_ARGS) $(INC_ARGS) 36 | 37 | .PHONY: clean 38 | clean: 39 | rm -f $(BIN) 40 | 41 | .PHONY: test 42 | 43 | test: $(BIN) 44 | @echo 'test redis' 45 | @(./test_redis > /dev/null && echo 'Succeed') || echo 'Failed' 46 | -------------------------------------------------------------------------------- /extensions/test/test_http_get.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "cocoflow.h" 6 | #include "cocoflow-http.h" 7 | 8 | using namespace std; 9 | 10 | static char *url = NULL; 11 | static char *buf = NULL; 12 | static size_t size = 1048576; 13 | 14 | class main_task: public ccf::user_task 15 | { 16 | void run() 17 | { 18 | int ret; 19 | const char *errmsg; 20 | 21 | ccf::http::get GET(ret, &errmsg, url, buf, size); 22 | await(GET); 23 | 24 | cerr << "Status Code: " << ret << endl; 25 | if (errmsg) 26 | cerr << "Reason Phrase: " << errmsg << endl; 27 | cerr << "Body Length: " << size << endl; 28 | if (size) 29 | { 30 | buf[size] = '\0'; 31 | cout << buf << endl; 32 | } 33 | } 34 | }; 35 | 36 | int main(int argc, char *argv[]) 37 | { 38 | if (argc < 2) 39 | { 40 | cerr << "Usage: " << argv[0] << " [bufsize=1048576]" << endl; 41 | return 1; 42 | } 43 | 44 | url = argv[1]; 45 | if (argc > 2) 46 | size = atoi(argv[2]); 47 | 48 | if (size) 49 | { 50 | buf = reinterpret_cast(malloc(size + 1)); 51 | if (!buf) 52 | return 2; 53 | } 54 | 55 | ccf::event_task::init(100); 56 | ccf::user_task::init(100); 57 | 58 | //ccf::set_debug(stderr); 59 | 60 | main_task tMain; 61 | ccf::cocoflow(tMain); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /extensions/test/test_http_post.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "cocoflow.h" 7 | #include "cocoflow-http.h" 8 | 9 | using namespace std; 10 | 11 | static char *url = NULL; 12 | static char *buf = NULL; 13 | static size_t size = 1048576; 14 | static string data; 15 | 16 | class main_task: public ccf::user_task 17 | { 18 | void run() 19 | { 20 | int ret; 21 | const char *errmsg; 22 | 23 | ccf::http::post POST(ret, &errmsg, url, data.data(), data.size(), buf, size); 24 | await(POST); 25 | 26 | cerr << "Status Code: " << ret << endl; 27 | if (errmsg) 28 | cerr << "Reason Phrase: " << errmsg << endl; 29 | cerr << "Body Length: " << size << endl; 30 | if (size) 31 | { 32 | buf[size] = '\0'; 33 | cout << buf << endl; 34 | } 35 | } 36 | }; 37 | 38 | int main(int argc, char *argv[]) 39 | { 40 | if (argc < 2) 41 | { 42 | cerr << "Usage: " << argv[0] << " [bufsize=1048576]" << endl; 43 | cerr << " POST data is read from stdin" << endl; 44 | return 1; 45 | } 46 | 47 | url = argv[1]; 48 | if (argc > 2) 49 | size = atoi(argv[2]); 50 | 51 | if (size) 52 | { 53 | buf = reinterpret_cast(malloc(size + 1)); 54 | if (!buf) 55 | return 2; 56 | } 57 | 58 | stringstream ss; 59 | ss << cin.rdbuf(); 60 | data = ss.str(); 61 | 62 | ccf::event_task::init(100); 63 | ccf::user_task::init(100); 64 | 65 | //ccf::set_debug(stderr); 66 | 67 | main_task tMain; 68 | ccf::cocoflow(tMain); 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /extensions/test/test_redis.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "cocoflow.h" 4 | #include "cocoflow-redis.h" 5 | 6 | #define TEST_PORT 6379 7 | #define TEST_KEY "test_key_for_cocoflow_redis" 8 | #define TEST_VAL "test_val_for_cocoflow_redis" 9 | #define TEST_KEY2 "test key for cocoflow redis" 10 | #define TEST_VAL2 "test val for cocoflow redis" 11 | 12 | using namespace std; 13 | 14 | static void show_reply(const redisReply *reply) 15 | { 16 | switch (reply->type) 17 | { 18 | case REDIS_REPLY_STRING: 19 | cout << "str: " << reply->str << endl; 20 | break; 21 | case REDIS_REPLY_ARRAY: 22 | cout << "array: (size=" << reply->elements << ")" << endl; 23 | break; 24 | case REDIS_REPLY_INTEGER: 25 | cout << "int: " << reply->integer << endl; 26 | break; 27 | case REDIS_REPLY_NIL: 28 | cout << "nil" << endl; 29 | break; 30 | case REDIS_REPLY_STATUS: 31 | cout << "status: " << reply->str << endl; 32 | break; 33 | case REDIS_REPLY_ERROR: 34 | cout << "error: " << reply->str << endl; 35 | break; 36 | default: 37 | cout << "bug" << endl; 38 | break; 39 | } 40 | } 41 | 42 | class main_task: public ccf::user_task 43 | { 44 | void run() 45 | { 46 | int ret; 47 | const redisReply *reply; 48 | 49 | ccf::redis r; 50 | 51 | ccf::redis::connect rc(&ret, r, "127.0.0.1", TEST_PORT); 52 | await(rc); 53 | cout << "connect: " << ret << endl; 54 | if (ret) 55 | cout << "errstr: " << r.errstr() << endl; 56 | 57 | ccf::redis::command* rset = new ccf::redis::command(NULL, NULL, r, "SET %s %s", TEST_KEY, TEST_VAL); 58 | start(rset); 59 | 60 | ccf::redis::command rget(&ret, &reply, r, "GET %s", TEST_KEY); 61 | await(rget); 62 | cout << "command(get): " << ret << endl; 63 | if (ret) 64 | cout << "errstr: " << r.errstr() << endl; 65 | else 66 | show_reply(reply); 67 | 68 | const char *argv[] = { 69 | "SET", 70 | TEST_KEY2, 71 | TEST_VAL2 72 | }; 73 | ccf::redis::command rset2(&ret, &reply, r, sizeof(argv)/sizeof(argv[0]), argv, NULL); 74 | await(rset2); 75 | cout << "command(set): " << ret << endl; 76 | if (ret) 77 | cout << "errstr: " << r.errstr() << endl; 78 | else 79 | show_reply(reply); 80 | 81 | const char *argv2[] = { 82 | "GET", 83 | TEST_KEY2 84 | }; 85 | ccf::redis::command rget2(&ret, &reply, r, sizeof(argv2)/sizeof(argv2[0]), argv2, NULL); 86 | await(rget2); 87 | cout << "command(get): " << ret << endl; 88 | if (ret) 89 | cout << "errstr: " << r.errstr() << endl; 90 | else 91 | show_reply(reply); 92 | 93 | ccf::redis::command rget3(&ret, &reply, r, 1, argv2, NULL); //test error 94 | await(rget3); 95 | cout << "command(get): " << ret << endl; 96 | if (ret) 97 | cout << "errstr: " << r.errstr() << endl; 98 | else 99 | show_reply(reply); 100 | } 101 | }; 102 | 103 | int main() 104 | { 105 | ccf::event_task::init(100); 106 | ccf::user_task::init(100); 107 | 108 | //ccf::set_debug(stderr); 109 | 110 | main_task tMain; 111 | ccf::cocoflow(tMain); 112 | return 0; 113 | } 114 | -------------------------------------------------------------------------------- /extensions/test/test_redis2.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "cocoflow.h" 4 | #include "cocoflow-redis.h" 5 | 6 | #define TEST_PORT 6379 7 | #define TEST_KEY "test_key_for_cocoflow_redis" 8 | #define TEST_VAL "test_val_for_cocoflow_redis" 9 | 10 | using namespace std; 11 | 12 | static void show_reply(const redisReply *reply) 13 | { 14 | switch (reply->type) 15 | { 16 | case REDIS_REPLY_STRING: 17 | cout << "str: " << reply->str << endl; 18 | break; 19 | case REDIS_REPLY_ARRAY: 20 | cout << "array: (size=" << reply->elements << ")" << endl; 21 | break; 22 | case REDIS_REPLY_INTEGER: 23 | cout << "int: " << reply->integer << endl; 24 | break; 25 | case REDIS_REPLY_NIL: 26 | cout << "nil" << endl; 27 | break; 28 | case REDIS_REPLY_STATUS: 29 | cout << "status: " << reply->str << endl; 30 | break; 31 | case REDIS_REPLY_ERROR: 32 | cout << "error: " << reply->str << endl; 33 | break; 34 | default: 35 | cout << "bug" << endl; 36 | break; 37 | } 38 | } 39 | 40 | static void connect_succeed(ccf::redis&, void*) 41 | { 42 | cerr << "connection succeed" << endl; 43 | } 44 | 45 | static void connect_failed(ccf::redis&, void*, ccf::redis::failed_type, const char *message) 46 | { 47 | cerr << message << endl; 48 | } 49 | 50 | class main_task: public ccf::user_task 51 | { 52 | void run() 53 | { 54 | int ret; 55 | const redisReply *reply; 56 | 57 | ccf::redis r; 58 | 59 | r.auto_connect("127.0.0.1", TEST_PORT); 60 | r.set_auto_connect_callback(connect_succeed, connect_failed); 61 | 62 | { 63 | ccf::redis::command rset(&ret, &reply, r, "SET %s %s", TEST_KEY, TEST_VAL); 64 | await(rset); 65 | cout << "command(set): " << ret << endl; 66 | if (ret) 67 | cout << "errstr: " << r.errstr() << endl; 68 | else 69 | show_reply(reply); 70 | 71 | ccf::sleep s(1000); 72 | await(s); 73 | } 74 | 75 | for (;;) 76 | { 77 | ccf::redis::command rget(&ret, &reply, r, "GET %s", TEST_KEY); 78 | await(rget); 79 | cout << "command(get): " << ret << endl; 80 | if (ret) 81 | cout << "errstr: " << r.errstr() << endl; 82 | else 83 | show_reply(reply); 84 | 85 | ccf::sleep s(1000); 86 | await(s); 87 | } 88 | } 89 | }; 90 | 91 | int main() 92 | { 93 | ccf::event_task::init(100); 94 | ccf::user_task::init(100); 95 | 96 | //ccf::set_debug(stderr); 97 | 98 | main_task tMain; 99 | ccf::cocoflow(tMain); 100 | return 0; 101 | } 102 | -------------------------------------------------------------------------------- /extensions/vc/cocoflow-extensions.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 10.00 3 | # Visual Studio 2008 4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libccf-http", "libccf-http.vcproj", "{85BC0E9B-AAA8-4B2D-BDD9-B8C4537D76C0}" 5 | EndProject 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_http_get", "test_http_get.vcproj", "{4CC4CC31-9D25-4173-BA60-EA5073951C83}" 7 | EndProject 8 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "test_http_post", "test_http_post.vcproj", "{4CC4CC31-9D25-4173-BA60-EA5073951C84}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Win32 = Debug|Win32 13 | Debug|Win64 = Debug|Win64 14 | Release|Win32 = Release|Win32 15 | Release|Win64 = Release|Win64 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {85BC0E9B-AAA8-4B2D-BDD9-B8C4537D76C0}.Debug|Win32.ActiveCfg = Debug|Win32 19 | {85BC0E9B-AAA8-4B2D-BDD9-B8C4537D76C0}.Debug|Win32.Build.0 = Debug|Win32 20 | {85BC0E9B-AAA8-4B2D-BDD9-B8C4537D76C0}.Debug|Win64.ActiveCfg = Debug|x64 21 | {85BC0E9B-AAA8-4B2D-BDD9-B8C4537D76C0}.Debug|Win64.Build.0 = Debug|x64 22 | {85BC0E9B-AAA8-4B2D-BDD9-B8C4537D76C0}.Release|Win32.ActiveCfg = Release|Win32 23 | {85BC0E9B-AAA8-4B2D-BDD9-B8C4537D76C0}.Release|Win32.Build.0 = Release|Win32 24 | {85BC0E9B-AAA8-4B2D-BDD9-B8C4537D76C0}.Release|Win64.ActiveCfg = Release|x64 25 | {85BC0E9B-AAA8-4B2D-BDD9-B8C4537D76C0}.Release|Win64.Build.0 = Release|x64 26 | {4CC4CC31-9D25-4173-BA60-EA5073951C83}.Debug|Win32.ActiveCfg = Debug|Win32 27 | {4CC4CC31-9D25-4173-BA60-EA5073951C83}.Debug|Win32.Build.0 = Debug|Win32 28 | {4CC4CC31-9D25-4173-BA60-EA5073951C83}.Debug|Win64.ActiveCfg = Debug|x64 29 | {4CC4CC31-9D25-4173-BA60-EA5073951C83}.Debug|Win64.Build.0 = Debug|x64 30 | {4CC4CC31-9D25-4173-BA60-EA5073951C83}.Release|Win32.ActiveCfg = Release|Win32 31 | {4CC4CC31-9D25-4173-BA60-EA5073951C83}.Release|Win32.Build.0 = Release|Win32 32 | {4CC4CC31-9D25-4173-BA60-EA5073951C83}.Release|Win64.ActiveCfg = Release|x64 33 | {4CC4CC31-9D25-4173-BA60-EA5073951C83}.Release|Win64.Build.0 = Release|x64 34 | {4CC4CC31-9D25-4173-BA60-EA5073951C84}.Debug|Win32.ActiveCfg = Debug|Win32 35 | {4CC4CC31-9D25-4173-BA60-EA5073951C84}.Debug|Win32.Build.0 = Debug|Win32 36 | {4CC4CC31-9D25-4173-BA60-EA5073951C84}.Debug|Win64.ActiveCfg = Debug|x64 37 | {4CC4CC31-9D25-4173-BA60-EA5073951C84}.Debug|Win64.Build.0 = Debug|x64 38 | {4CC4CC31-9D25-4173-BA60-EA5073951C84}.Release|Win32.ActiveCfg = Release|Win32 39 | {4CC4CC31-9D25-4173-BA60-EA5073951C84}.Release|Win32.Build.0 = Release|Win32 40 | {4CC4CC31-9D25-4173-BA60-EA5073951C84}.Release|Win64.ActiveCfg = Release|x64 41 | {4CC4CC31-9D25-4173-BA60-EA5073951C84}.Release|Win64.Build.0 = Release|x64 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | EndGlobal 47 | -------------------------------------------------------------------------------- /extensions/vc/libccf-http.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 15 | 18 | 19 | 20 | 21 | 22 | 29 | 32 | 35 | 38 | 41 | 44 | 57 | 60 | 63 | 66 | 69 | 72 | 75 | 78 | 81 | 84 | 85 | 93 | 96 | 99 | 102 | 105 | 108 | 118 | 121 | 124 | 127 | 130 | 133 | 136 | 139 | 142 | 145 | 146 | 153 | 156 | 159 | 162 | 165 | 169 | 182 | 185 | 188 | 191 | 194 | 197 | 200 | 203 | 206 | 209 | 210 | 218 | 221 | 224 | 227 | 230 | 234 | 244 | 247 | 250 | 253 | 256 | 259 | 262 | 265 | 268 | 271 | 272 | 273 | 274 | 275 | 276 | 281 | 284 | 285 | 286 | 291 | 292 | 297 | 298 | 299 | 300 | 301 | 302 | -------------------------------------------------------------------------------- /extensions/vcbuild.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | cd %~dp0 4 | 5 | set CCF_PLATFORM=x86 6 | if "%PROCESSOR_ARCHITECTURE%"=="AMD64" set CCF_PLATFORM=x64 7 | if "%1"=="x86" set CCF_PLATFORM=x86 8 | if "%1"=="x64" set CCF_PLATFORM=x64 9 | 10 | set CCF_MS_PLATFORM=WIN32 11 | if "%CCF_PLATFORM%"=="x64" set CCF_MS_PLATFORM=WIN64 12 | set CCF_LIB_PATH= 13 | if "%CCF_PLATFORM%"=="x64" set CCF_LIB_PATH=x64\ 14 | 15 | @rem Look for Visual Studio 2013 16 | if not defined VS120COMNTOOLS goto vc-set-2012 17 | if not exist "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2012 18 | call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" %CCF_PLATFORM% 19 | goto upgrade 20 | 21 | :vc-set-2012 22 | @rem Look for Visual Studio 2012 23 | if not defined VS110COMNTOOLS goto vc-set-2010 24 | if not exist "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2010 25 | call "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" %CCF_PLATFORM% 26 | goto upgrade 27 | 28 | :vc-set-2010 29 | @rem Look for Visual Studio 2010 30 | if not defined VS100COMNTOOLS goto vc-set-2008 31 | if not exist "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2008 32 | call "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" %CCF_PLATFORM% 33 | goto upgrade 34 | 35 | :vc-set-2008 36 | @rem Look for Visual Studio 2008 37 | if not defined VS90COMNTOOLS goto vc-set-notfound 38 | if not exist "%VS90COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-notfound 39 | call "%VS90COMNTOOLS%\..\..\vc\vcvarsall.bat" %CCF_PLATFORM% 40 | goto msbuild 41 | 42 | :vc-set-notfound 43 | echo Error: Visual Studio not found 44 | goto exit 45 | 46 | :upgrade 47 | echo Upgrading for Visual Studio ... 48 | devenv /upgrade vc\cocoflow-extensions.sln 49 | 50 | :msbuild 51 | echo Compiling libccf-http ... 52 | msbuild vc\cocoflow-extensions.sln /t:libccf-http /p:Configuration=Debug /p:Platform="%CCF_MS_PLATFORM%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo 53 | msbuild vc\cocoflow-extensions.sln /t:libccf-http /p:Configuration=Release /p:Platform="%CCF_MS_PLATFORM%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo 54 | xcopy /Y vc\%CCF_LIB_PATH%Debug\libccf-http.lib ..\lib\Debug\ > nul 55 | xcopy /Y vc\%CCF_LIB_PATH%Release\libccf-http.lib ..\lib\Release\ > nul 56 | 57 | echo Compiling test ... 58 | msbuild vc\cocoflow-extensions.sln /t:test_http_get,test_http_post /p:Configuration=Debug /p:Platform="%CCF_MS_PLATFORM%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo 59 | msbuild vc\cocoflow-extensions.sln /t:test_http_get,test_http_post /p:Configuration=Release /p:Platform="%CCF_MS_PLATFORM%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo 60 | 61 | :exit 62 | pause 63 | -------------------------------------------------------------------------------- /include/cocoflow-http.h: -------------------------------------------------------------------------------- 1 | #ifndef __COCOFLOW_HTTP_H__ 2 | #define __COCOFLOW_HTTP_H__ 3 | 4 | #include "cocoflow.h" 5 | 6 | namespace ccf { 7 | 8 | namespace http { 9 | 10 | //retcode 11 | enum { 12 | OK = 200, 13 | unfinished = -1, 14 | err_url_parse = -2, 15 | err_dns_resolve = -3, 16 | err_tcp_connect = -4, 17 | err_send_request = -5, 18 | err_recv_response = -6, 19 | err_response_header_parse = -7, 20 | err_response_body_parse = -8, 21 | err_response_body_too_long = -9, 22 | Continue = 100, 23 | SwitchingProtocols = 101, 24 | Created = 201, 25 | Accepted = 202, 26 | NonAuthoritativeInformation = 203, 27 | NoContent = 204, 28 | ResetContent = 205, 29 | PartialContent = 206, 30 | MultipleChoices = 300, 31 | MovedPermanently = 301, 32 | Found = 302, 33 | SeeOther = 303, 34 | NotModified = 304, 35 | UseProxy = 305, 36 | TemporaryRedirect = 307, 37 | BadRequest = 400, 38 | Unauthorized = 401, 39 | PaymentRequired = 402, 40 | Forbidden = 403, 41 | NotFound = 404, 42 | MethodNotAllowed = 405, 43 | NotAcceptable = 406, 44 | ProxyAuthenticationRequired = 407, 45 | RequestTimeout = 408, 46 | Conflict = 409, 47 | Gone = 410, 48 | LengthRequired = 411, 49 | PreconditionFailed = 412, 50 | RequestEntityTooLarge = 413, 51 | RequestURITooLong = 414, 52 | UnsupportedMediaType = 415, 53 | RequestedRangeNotSatisfiable = 416, 54 | ExpectationFailed = 417, 55 | InternalServerError = 500, 56 | NotImplemented = 501, 57 | BadGateway = 502, 58 | ServiceUnavailable = 503, 59 | GatewayTimeout = 504, 60 | HTTPVersionNotSupported = 505, 61 | }; 62 | 63 | class get : public event_task 64 | { 65 | public: 66 | get(int &ret, const char **errmsg, const char *url, void *buf, size_t &len); 67 | virtual ~get(); 68 | private: 69 | get(const get&); 70 | get& operator=(const get&); 71 | virtual void run(); 72 | virtual void cancel(); 73 | int &ret; 74 | const char **errmsg; 75 | const char *url; 76 | void *buf; 77 | size_t &len; 78 | template friend class __client; 79 | }; 80 | 81 | class post : public event_task 82 | { 83 | public: 84 | post(int &ret, const char **errmsg, const char *url, const void *pbuf, size_t plen, void *buf, size_t &len); 85 | virtual ~post(); 86 | private: 87 | post(const post&); 88 | post& operator=(const post&); 89 | virtual void run(); 90 | virtual void cancel(); 91 | int &ret; 92 | const char **errmsg; 93 | const char *url; 94 | const void *pbuf; 95 | size_t plen; 96 | void *buf; 97 | size_t &len; 98 | template friend class __client; 99 | }; 100 | 101 | } /* end of namespace http */ 102 | 103 | } /* end of namespace ccf */ 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /include/cocoflow-redis.h: -------------------------------------------------------------------------------- 1 | #ifndef __COCOFLOW_REDIS_H__ 2 | #define __COCOFLOW_REDIS_H__ 3 | 4 | #include "cocoflow.h" 5 | 6 | /* Simplified hiredis.h */ 7 | extern "C" { 8 | #ifndef __disable_simplify_hiredis_h__ 9 | #define REDIS_UNFINISHED -2 10 | #define REDIS_ERR -1 11 | #define REDIS_OK 0 12 | 13 | #define REDIS_ERR_IO 1 /* Error in read or write */ 14 | #define REDIS_ERR_EOF 3 /* End of file */ 15 | #define REDIS_ERR_PROTOCOL 4 /* Protocol error */ 16 | #define REDIS_ERR_OOM 5 /* Out of memory */ 17 | #define REDIS_ERR_OTHER 2 /* Everything else... */ 18 | 19 | #define REDIS_REPLY_STRING 1 20 | #define REDIS_REPLY_ARRAY 2 21 | #define REDIS_REPLY_INTEGER 3 22 | #define REDIS_REPLY_NIL 4 23 | #define REDIS_REPLY_STATUS 5 24 | #define REDIS_REPLY_ERROR 6 25 | 26 | typedef struct redisReply { 27 | int type; /* REDIS_REPLY_* */ 28 | long long integer; /* The integer when type is REDIS_REPLY_INTEGER */ 29 | int len; /* Length of string */ 30 | char *str; /* Used for both REDIS_REPLY_ERROR and REDIS_REPLY_STRING */ 31 | size_t elements; /* number of elements, for REDIS_REPLY_ARRAY */ 32 | struct redisReply **element; /* elements vector for REDIS_REPLY_ARRAY */ 33 | } redisReply; 34 | #endif 35 | } 36 | 37 | namespace ccf { 38 | 39 | class redis 40 | { 41 | public: 42 | class connect : public event_task 43 | { 44 | public: 45 | connect(int* ret, redis& handle, const char* ip, int port); 46 | virtual ~connect(); 47 | private: 48 | connect(const connect&); 49 | connect& operator=(const connect&); 50 | virtual void run(); 51 | virtual void cancel(); 52 | int* ret; 53 | redis& handle; 54 | char* ip; 55 | int port; 56 | friend class redis; 57 | }; 58 | class command : public event_task 59 | { 60 | public: 61 | command(int* ret, const redisReply** reply, redis& handle, const char* format, ...); 62 | command(int* ret, const redisReply** reply, redis& handle, int argc, const char** argv, const size_t* argvlen = NULL); 63 | virtual ~command(); 64 | private: 65 | command(const command&); 66 | command& operator=(const command&); 67 | virtual void run(); 68 | virtual void cancel(); 69 | int* ret; 70 | const redisReply** reply; 71 | redis& handle; 72 | command** req; 73 | int redis_err; 74 | friend class redis; 75 | }; 76 | redis(); 77 | ~redis(); 78 | const char* errstr(); 79 | int auto_connect(const char* ip, int port, int timeout = 2000); //ms 80 | /* set_auto_connect_callback is only for log/monitor */ 81 | enum failed_type { 82 | failed_exception = 1, //an error occurred on connecting 83 | failed_disconnect, //connection is closed by peer 84 | failed_timeout //connecting timeout 85 | }; 86 | typedef void auto_connect_succeed (redis& handle, void* data); 87 | typedef void auto_connect_failed (redis& handle, void* data, failed_type type, const char *message); 88 | void set_auto_connect_callback(auto_connect_succeed* succeed, auto_connect_failed* failed, void* data = NULL); 89 | private: 90 | void* context; 91 | void* timer; //for connect 92 | int cur_reconnect_interval; 93 | int timeout; 94 | auto_connect_succeed* succeed; 95 | auto_connect_failed* failed; 96 | void* data; 97 | std::string ip; 98 | int port; 99 | bool old_opened; //connect new need close old 100 | int connect_now(bool); 101 | int connect_coming(bool); 102 | static void connect_cb(const struct redisAsyncContext*, int); 103 | static void command_cb(struct redisAsyncContext*, void*, void*); 104 | static void auto_connect_cb(const struct redisAsyncContext*, int); 105 | static void auto_connect_closed_cb(const struct redisAsyncContext*, int); 106 | static void auto_connect_timeout_cb(uv_timer_t*, int); 107 | static void auto_reconnect_next_cb(uv_timer_t*, int); 108 | }; 109 | 110 | } /* end of namespace ccf */ 111 | 112 | #endif 113 | -------------------------------------------------------------------------------- /lib/chishaxie: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/chishaxie/cocoflow/4c7c0978940b398d972150ee5b0f0ad8530c396f/lib/chishaxie -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | C_ARGS = -g -Wall -O2 2 | CC = gcc 3 | CX = g++ 4 | 5 | UV_VERSION=0.10.27 6 | UV_BUILDTYPE=Release 7 | 8 | LIB = ../lib/libuv.a ../lib/libccf.a 9 | 10 | INC_ARGS = -I../include 11 | 12 | all: $(LIB) 13 | 14 | ../lib/libccf.a: cocoflow.o sleep.o sync.o udp.o tcp.o getaddrinfo.o tools.o max_map_count.o 15 | ar cr $@ $^ 16 | 17 | cocoflow.o: cocoflow.cc cocoflow-comm.h max_map_count.h ../include/cocoflow.h uv/uv.h 18 | $(CX) $(C_ARGS) -fPIC -c -o $@ cocoflow.cc $(INC_ARGS) 19 | 20 | sleep.o: sleep.cc cocoflow-comm.h ../include/cocoflow.h uv/uv.h 21 | $(CX) $(C_ARGS) -fPIC -c -o $@ sleep.cc $(INC_ARGS) 22 | 23 | sync.o: sync.cc cocoflow-comm.h ../include/cocoflow.h uv/uv.h 24 | $(CX) $(C_ARGS) -fPIC -c -o $@ sync.cc $(INC_ARGS) 25 | 26 | udp.o: udp.cc cocoflow-comm.h ../include/cocoflow.h uv/uv.h 27 | $(CX) $(C_ARGS) -fPIC -c -o $@ udp.cc $(INC_ARGS) 28 | 29 | tcp.o: tcp.cc cocoflow-comm.h ../include/cocoflow.h uv/uv.h 30 | $(CX) $(C_ARGS) -fPIC -c -o $@ tcp.cc $(INC_ARGS) 31 | 32 | getaddrinfo.o: getaddrinfo.cc cocoflow-comm.h ../include/cocoflow.h uv/uv.h 33 | $(CX) $(C_ARGS) -fPIC -c -o $@ getaddrinfo.cc $(INC_ARGS) 34 | 35 | tools.o: tools.cc cocoflow-comm.h ../include/cocoflow.h uv/uv.h 36 | $(CX) $(C_ARGS) -fPIC -c -o $@ tools.cc $(INC_ARGS) 37 | 38 | max_map_count.o: max_map_count.c max_map_count.h 39 | $(CC) $(C_ARGS) -fPIC -c -o $@ max_map_count.c 40 | 41 | uv/uv.h: ../deps/libuv.a 42 | @mkdir uv; cp -r ../deps/libuv-$(UV_VERSION)/include/* uv/ 43 | 44 | ../lib/libuv.a: ../deps/libuv.a 45 | @cp $^ $@ 46 | 47 | ../deps/libuv.a: ../deps/libuv-$(UV_VERSION).zip ../deps/gyp.zip 48 | @echo "Dependency analysis ..." 49 | @cd ../deps/; unzip libuv-$(UV_VERSION).zip > /dev/null; unzip gyp.zip > /dev/null; cd libuv-$(UV_VERSION)/; mkdir build; cd build/; mkdir gyp; cd gyp; cp -r ../../../gyp/* ./; cd ../../../../src/ 50 | @echo "Compiling libuv ..." 51 | @cd ../deps/libuv-$(UV_VERSION)/; ./gyp_uv.py -f make > /dev/null; cd out/; make BUILDTYPE=$(UV_BUILDTYPE) > /dev/null; cd ../../../src/; 52 | @cp ../deps/libuv-$(UV_VERSION)/out/$(UV_BUILDTYPE)/libuv.a $@ 53 | @echo "Compiled libuv" 54 | 55 | .PHONY: clean 56 | clean: 57 | rm -f $(LIB) *.o 58 | -------------------------------------------------------------------------------- /src/cocoflow-comm.h: -------------------------------------------------------------------------------- 1 | #ifndef __COCOFLOW_COMM_H__ 2 | #define __COCOFLOW_COMM_H__ 3 | 4 | #include 5 | #include 6 | 7 | #if !defined(_WIN32) && !defined(_WIN64) 8 | # include 9 | # include 10 | # include 11 | #endif 12 | 13 | #if defined(__GNUG__) 14 | # include 15 | #endif 16 | 17 | extern "C" { 18 | #define __disable_simplify_uv_h__ 19 | #include "uv/uv.h" 20 | } 21 | 22 | #include "cocoflow.h" 23 | 24 | #define CLASS_TIPS_MAX_LEN 2048 25 | 26 | #if !defined(_MSC_VER) 27 | #define FATAL_ERROR(fmt, args...) \ 28 | do { \ 29 | fprintf(stderr, "[FATAL]: " fmt "\n", ##args); \ 30 | abort(); \ 31 | } while(0) 32 | #define LOG_DEBUG(fmt, args...) \ 33 | do { \ 34 | uint32 ns = uv_hrtime()%1000000000; \ 35 | time_t s = time(NULL); \ 36 | struct tm date = *localtime(&s); \ 37 | fprintf(global_debug_file, "[%02u:%02u:%02u.%09u] [DEBUG]: " fmt "\n", date.tm_hour, date.tm_min, date.tm_sec, ns, ##args); \ 38 | } while(0) 39 | #else 40 | #pragma warning(disable:4996) 41 | #pragma warning(disable:4390) 42 | #define FATAL_ERROR(fmt, ...) \ 43 | do { \ 44 | fprintf(stderr, "[FATAL]: " fmt "\n", __VA_ARGS__); \ 45 | abort(); \ 46 | } while(0) 47 | #define LOG_DEBUG(fmt, ...) \ 48 | do { \ 49 | uint32 ns = uv_hrtime()%1000000000; \ 50 | time_t s = time(NULL); \ 51 | struct tm date = *localtime(&s); \ 52 | fprintf(global_debug_file, "[%02u:%02u:%02u.%09u] [DEBUG]: " fmt "\n", date.tm_hour, date.tm_min, date.tm_sec, ns, __VA_ARGS__); \ 53 | } while(0) 54 | #endif 55 | 56 | #define CHECK(x) \ 57 | do { \ 58 | if (ccf_unlikely(!(x))) \ 59 | { \ 60 | fprintf(stderr, "[ASSERT]: " #x " failed at " __FILE__ ":%u\n", __LINE__); \ 61 | abort(); \ 62 | } \ 63 | } while(0) 64 | 65 | namespace ccf { 66 | 67 | #define task_set_status(task, status) \ 68 | do { \ 69 | (task)->_info = ((task)->_info & 0xf0) | (status); \ 70 | } while(0) 71 | #define task_get_status(task) ((task)->_info & 0x0f) 72 | 73 | #define task_info_uninterruptable 0x10 74 | #define task_info_all_any 0x20 75 | 76 | #define task_set_uninterruptable(task) \ 77 | do { \ 78 | (task)->_info |= task_info_uninterruptable; \ 79 | } while(0) 80 | #define task_is_uninterruptable(task) ((task)->_info & task_info_uninterruptable) 81 | 82 | #define task_set_all_any(task) \ 83 | do { \ 84 | (task)->_info |= task_info_all_any; \ 85 | } while(0) 86 | #define task_is_all_any(task) ((task)->_info & task_info_all_any) 87 | 88 | #if defined(_WIN32) || defined(_WIN64) 89 | typedef LPVOID coroutine; 90 | #define coroutine_by_thread(runtime) \ 91 | do { \ 92 | (*(runtime)) = ConvertThreadToFiberEx(NULL, FIBER_FLAG_FLOAT_SWITCH); \ 93 | CHECK((*(runtime)) != NULL); \ 94 | } while(0) 95 | #define coroutine_create(runtime, mem, size, id) \ 96 | do { \ 97 | (*(runtime)) = CreateFiberEx(size, size, FIBER_FLAG_FLOAT_SWITCH, reinterpret_cast(__task_runtime), reinterpret_cast(id)); \ 98 | CHECK((*(runtime)) != NULL); \ 99 | } while(0) 100 | #define coroutine_switch(from, to, from_id, to_id) \ 101 | do { \ 102 | (*from) = GetCurrentFiber(); \ 103 | CHECK((*from) != NULL); \ 104 | SwitchToFiber(*to); \ 105 | } while(0) 106 | #define coroutine_memory_alloc(total_size) reinterpret_cast(0x1000) 107 | #define coroutine_memory_protect(mem, size) ; 108 | #else 109 | typedef ucontext_t coroutine; 110 | #define coroutine_by_thread(runtime) ; 111 | #define coroutine_create(runtime, mem, size, id) \ 112 | do { \ 113 | CHECK(getcontext(runtime) == 0); \ 114 | (runtime)->uc_link = &global_loop_running; \ 115 | (runtime)->uc_stack.ss_sp = (mem); \ 116 | (runtime)->uc_stack.ss_size = (size); \ 117 | makecontext(runtime, reinterpret_cast(__task_runtime), 1, (long)id); \ 118 | } while(0) 119 | #define coroutine_switch(from, to, from_id, to_id) \ 120 | do { \ 121 | if (ccf_unlikely(swapcontext(from, to))) \ 122 | FATAL_ERROR("Swap running failed, %u -> %u", from_id, to_id); \ 123 | } while(0) 124 | #define coroutine_memory_alloc(total_size) \ 125 | mmap(NULL, total_size, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) 126 | #define coroutine_memory_protect(mem, size) \ 127 | do { \ 128 | CHECK(mprotect(mem, size, PROT_NONE) == 0); \ 129 | } while(0) 130 | #endif 131 | 132 | extern coroutine* global_running_manager; 133 | extern coroutine global_loop_running; 134 | extern event_task* global_current_task; 135 | extern bool global_signal_canceled; 136 | extern FILE* global_debug_file; 137 | extern char global_debug_output_src[CLASS_TIPS_MAX_LEN]; 138 | extern char global_debug_output_dst[CLASS_TIPS_MAX_LEN]; 139 | 140 | inline const char* __task_to_tips(const event_task* et, char* tips, bool show_reuse = false) 141 | { 142 | if (et != NULL) 143 | { 144 | if (!show_reuse || !et->reuse) 145 | { 146 | #if defined(__GNUG__) 147 | size_t len = CLASS_TIPS_MAX_LEN; 148 | abi::__cxa_demangle(typeid(*et).name(), tips, &len, NULL); 149 | #else 150 | strcpy(tips, typeid(*et).name()); 151 | #endif 152 | } 153 | else 154 | { 155 | const event_task* reuse = et->reuse; 156 | while (reuse->reuse) 157 | reuse = reuse->reuse; 158 | #if defined(__GNUG__) 159 | char* _t0 = abi::__cxa_demangle(typeid(*et).name(), NULL, NULL, NULL); 160 | char* _t1 = abi::__cxa_demangle(typeid(*reuse).name(), NULL, NULL, NULL); 161 | sprintf(tips, "%s|%s", _t0, _t1); 162 | free(_t0); 163 | free(_t1); 164 | #else 165 | sprintf(tips, "%s|%s", typeid(*et).name(), typeid(*reuse).name()); 166 | #endif 167 | } 168 | } 169 | else 170 | strcpy(tips, "???"); 171 | return tips; 172 | } 173 | 174 | #define src_to_tips(src) __task_to_tips(src, global_debug_output_src) 175 | #define dst_to_tips(dst) __task_to_tips(dst, global_debug_output_dst) 176 | #define src_to_tips_pro(src) __task_to_tips(src, global_debug_output_src, true) 177 | #define dst_to_tips_pro(dst) __task_to_tips(dst, global_debug_output_dst, true) 178 | 179 | static inline uv_loop_t* loop() 180 | { 181 | static uv_loop_t* __loop = NULL; 182 | if (ccf_unlikely(__loop == NULL)) 183 | __loop = uv_default_loop(); 184 | return __loop; 185 | } 186 | 187 | #define interrupt_canceled _ic 188 | 189 | struct interrupt_canceled 190 | { 191 | interrupt_canceled(int level) : level(level) {} 192 | const int level; 193 | }; 194 | 195 | static inline void swap_running(uint32 cur, uint32 next) 196 | { 197 | coroutine *cur_runing = (cur == EVENT_LOOP_ID) ? (&global_loop_running) : (global_running_manager + cur), 198 | *next_runing = (next == EVENT_LOOP_ID) ? (&global_loop_running) : (global_running_manager + next); 199 | global_current_task = (next == EVENT_LOOP_ID) ? (NULL) : (global_task_manager[next]); 200 | if (ccf_unlikely(global_debug_file)) 201 | { 202 | if (cur == EVENT_LOOP_ID) 203 | LOG_DEBUG("[Switch] EventLoop -> %u-<%s>", next, dst_to_tips_pro(global_task_manager[next])); 204 | else if (next == EVENT_LOOP_ID) 205 | LOG_DEBUG("[Switch] %u-<%s> -> EventLoop", cur, src_to_tips_pro(global_task_manager[cur])); 206 | else 207 | LOG_DEBUG("[Switch] %u-<%s> -> %u-<%s>", cur, src_to_tips_pro(global_task_manager[cur]), next, dst_to_tips_pro(global_task_manager[next])); 208 | } 209 | coroutine_switch(cur_runing, next_runing, cur, next); 210 | global_current_task = (cur == EVENT_LOOP_ID) ? (NULL) : (global_task_manager[cur]); 211 | } 212 | 213 | /* false means interrupt by cancel */ 214 | inline bool __task_yield(event_task* cur) 215 | { 216 | uint32 source = cur->_unique_id, target = cur->block_to; 217 | cur->block_to = EVENT_LOOP_ID; //switch to block_to only once 218 | swap_running(source, target); 219 | if (global_signal_canceled) 220 | { 221 | global_signal_canceled = false; 222 | if (task_get_status(cur) != canceled) //Indirect 223 | { 224 | task_set_status(cur, canceled); 225 | throw interrupt_canceled(0); 226 | } 227 | else 228 | cur->cancel(); 229 | return false; 230 | } 231 | else 232 | return true; 233 | } 234 | 235 | inline void __task_stand(event_task* cur) 236 | { 237 | swap_running(EVENT_LOOP_ID, cur->_unique_id); 238 | } 239 | 240 | /***** uv *****/ 241 | 242 | void free_self_close_cb(uv_handle_t* handle); 243 | 244 | /***** sockaddr *****/ 245 | 246 | struct sockaddr_in6 sockaddr_in_into_sockaddr_in6(const struct sockaddr_in& addr); 247 | struct sockaddr_in sockaddr_in_outof_sockaddr_in6(const struct sockaddr_in6& addr); 248 | 249 | } 250 | 251 | #endif 252 | -------------------------------------------------------------------------------- /src/getaddrinfo.cc: -------------------------------------------------------------------------------- 1 | #include "cocoflow-comm.h" 2 | 3 | namespace ccf { 4 | 5 | /***** getaddrinfo *****/ 6 | 7 | getaddrinfo::getaddrinfo(int& ret, struct addrinfo** result, const char** errmsg, 8 | const char* node, const char* service, const struct addrinfo* hints) 9 | : req(NULL), ret(ret), result(result), errmsg(errmsg), node(node), service(service), hints(hints) 10 | { 11 | this->ret = -1; 12 | if (this->result) 13 | *this->result = NULL; 14 | if (this->errmsg) 15 | *this->errmsg = NULL; 16 | } 17 | 18 | void getaddrinfo::getaddrinfo_cb(uv_getaddrinfo_t* req, int status, struct addrinfo* result) 19 | { 20 | if (status == 0) 21 | { 22 | if (req->data) 23 | { 24 | reinterpret_cast(req->data)->ret = 0; 25 | if (reinterpret_cast(req->data)->result) 26 | *reinterpret_cast(req->data)->result = result; 27 | else 28 | uv_freeaddrinfo(result); 29 | __task_stand(reinterpret_cast(req->data)); 30 | } 31 | else 32 | uv_freeaddrinfo(result); 33 | } 34 | else 35 | { 36 | CHECK(result == NULL); 37 | if (req->data) 38 | { 39 | reinterpret_cast(req->data)->ret = status; 40 | if (reinterpret_cast(req->data)->errmsg) 41 | *reinterpret_cast(req->data)->errmsg = uv_strerror(uv_last_error(loop())); 42 | __task_stand(reinterpret_cast(req->data)); 43 | } 44 | } 45 | free(req); 46 | } 47 | 48 | void getaddrinfo::run() 49 | { 50 | this->req = malloc(sizeof(uv_getaddrinfo_t)); 51 | CHECK(this->req != NULL); 52 | int status = uv_getaddrinfo(loop(), reinterpret_cast(this->req), getaddrinfo::getaddrinfo_cb, 53 | this->node, this->service, this->hints); 54 | if (status == 0) 55 | { 56 | reinterpret_cast(this->req)->data = this; 57 | (void)__task_yield(this); 58 | } 59 | else 60 | { 61 | this->ret = status; 62 | if (this->errmsg) 63 | *this->errmsg = uv_strerror(uv_last_error(loop())); 64 | free(this->req); 65 | } 66 | } 67 | 68 | void getaddrinfo::cancel() 69 | { 70 | if (this->errmsg) 71 | *this->errmsg = "It was canceled"; 72 | (void)uv_cancel(reinterpret_cast(this->req)); //may fail in linux, must fail in win 73 | reinterpret_cast(this->req)->data = NULL; 74 | } 75 | 76 | getaddrinfo::~getaddrinfo() 77 | { 78 | } 79 | 80 | void getaddrinfo::freeaddrinfo(struct addrinfo* result) 81 | { 82 | uv_freeaddrinfo(result); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/max_map_count.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | int get_max_map_count() 11 | { 12 | int ret = 0; 13 | 14 | struct __sysctl_args args; 15 | int name[] = {CTL_VM, VM_MAX_MAP_COUNT}; 16 | size_t len = sizeof(ret); 17 | 18 | memset(&args, 0, sizeof(args)); 19 | args.name = name; 20 | args.nlen = sizeof(name)/sizeof(name[0]); 21 | args.oldval = &ret; 22 | args.oldlenp = &len; 23 | 24 | /* int _sysctl(struct __sysctl_args *args); */ 25 | if (syscall(SYS__sysctl, &args) == -1) 26 | return -1; 27 | else 28 | return ret; 29 | } 30 | -------------------------------------------------------------------------------- /src/max_map_count.h: -------------------------------------------------------------------------------- 1 | #ifndef __MAX_MAP_COUNT_H__ 2 | #define __MAX_MAP_COUNT_H__ 3 | 4 | #ifdef __cplusplus 5 | extern "C"{ 6 | #endif 7 | 8 | int get_max_map_count(); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/sleep.cc: -------------------------------------------------------------------------------- 1 | #include "cocoflow-comm.h" 2 | 3 | namespace ccf { 4 | 5 | /***** sleep *****/ 6 | 7 | sleep::sleep(uint64 timeout) 8 | : timeout(timeout), timer(NULL) 9 | { 10 | } 11 | 12 | static void sleep_cb(uv_timer_t* req, int status) 13 | { 14 | CHECK(status == 0); 15 | __task_stand(reinterpret_cast(req->data)); 16 | } 17 | 18 | void sleep::run() 19 | { 20 | this->timer = malloc(sizeof(uv_timer_t)); 21 | CHECK(this->timer != NULL); 22 | CHECK(uv_timer_init(loop(), reinterpret_cast(this->timer)) == 0); 23 | reinterpret_cast(this->timer)->data = this; 24 | CHECK(uv_timer_start(reinterpret_cast(this->timer), sleep_cb, this->timeout, 0) == 0); 25 | if (!__task_yield(this)) 26 | return; 27 | uv_close(reinterpret_cast(this->timer), free_self_close_cb); 28 | } 29 | 30 | void sleep::cancel() 31 | { 32 | uv_close(reinterpret_cast(this->timer), free_self_close_cb); 33 | } 34 | 35 | sleep::~sleep() 36 | { 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/sync.cc: -------------------------------------------------------------------------------- 1 | #include "cocoflow-comm.h" 2 | 3 | namespace ccf { 4 | 5 | /***** sync *****/ 6 | 7 | sync::sync() 8 | : async(NULL), named(false) 9 | { 10 | } 11 | 12 | sync::sync(long id) 13 | : id(id), async(NULL), named(true) 14 | { 15 | } 16 | 17 | static void sync_cb(uv_async_t* async, int status) 18 | { 19 | CHECK(status == 0); 20 | __task_stand(reinterpret_cast(async->data)); 21 | } 22 | 23 | void sync::run() 24 | { 25 | if (this->named) 26 | { 27 | std::pair::iterator, bool> ret = sync::ids.insert(std::pair(this->id, this)); 28 | CHECK(ret.second == true); 29 | this->pos = ret.first; 30 | } 31 | this->async = malloc(sizeof(uv_async_t)); 32 | CHECK(this->async != NULL); 33 | CHECK(uv_async_init(loop(), reinterpret_cast(this->async), sync_cb) == 0); 34 | reinterpret_cast(this->async)->data = this; 35 | if (!__task_yield(this)) 36 | return; 37 | if (this->named) 38 | sync::ids.erase(this->pos); 39 | uv_close(reinterpret_cast(this->async), free_self_close_cb); 40 | this->async = NULL; 41 | } 42 | 43 | void sync::cancel() 44 | { 45 | if (this->named) 46 | sync::ids.erase(this->pos); 47 | uv_close(reinterpret_cast(this->async), free_self_close_cb); 48 | this->async = NULL; 49 | } 50 | 51 | sync::~sync() 52 | { 53 | } 54 | 55 | int sync::notify(sync* obj) 56 | { 57 | if (obj->async) 58 | { 59 | CHECK(uv_async_send(reinterpret_cast(obj->async)) == 0); 60 | return 0; 61 | } 62 | else 63 | return -1; 64 | } 65 | 66 | int sync::notify(long id) 67 | { 68 | std::map::iterator it = sync::ids.find(id); 69 | if (it != sync::ids.end()) 70 | { 71 | CHECK(uv_async_send(reinterpret_cast(it->second->async)) == 0); 72 | return 0; 73 | } 74 | else 75 | return -1; 76 | } 77 | 78 | std::map sync::ids; 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/tools.cc: -------------------------------------------------------------------------------- 1 | #include "cocoflow-comm.h" 2 | 3 | #if defined(_MSC_VER) 4 | #pragma warning(disable:4748) 5 | #endif 6 | 7 | namespace ccf { 8 | 9 | /***** tools *****/ 10 | 11 | union addr_ip { 12 | struct sockaddr_in6 addr6; 13 | struct sockaddr_in addr4; 14 | }; 15 | 16 | struct sockaddr_in6 sockaddr_in_into_sockaddr_in6(const struct sockaddr_in& addr) 17 | { 18 | union addr_ip uaddr; 19 | uaddr.addr4 = addr; 20 | return uaddr.addr6; 21 | } 22 | 23 | struct sockaddr_in sockaddr_in_outof_sockaddr_in6(const struct sockaddr_in6& addr) 24 | { 25 | union addr_ip uaddr; 26 | uaddr.addr6 = addr; 27 | return uaddr.addr4; 28 | } 29 | 30 | struct sockaddr_in ip_to_addr(const char* ipv4, int port) 31 | { 32 | return uv_ip4_addr(ipv4, port); 33 | } 34 | 35 | struct sockaddr_in6 ip_to_addr6(const char* ipv6, int port) 36 | { 37 | return uv_ip6_addr(ipv6, port); 38 | } 39 | 40 | std::string ip_to_str(const struct sockaddr* addr) 41 | { 42 | if (addr->sa_family == AF_INET) 43 | return ip_to_str(*reinterpret_cast(addr)); 44 | else if (addr->sa_family == AF_INET6) 45 | return ip_to_str(*reinterpret_cast(addr)); 46 | else 47 | return std::string("Not IP Address"); 48 | } 49 | 50 | std::string ip_to_str(const struct sockaddr_in& addr) 51 | { 52 | char str[112], tmp[16]; 53 | if (uv_ip4_name(const_cast(&addr), str, sizeof(str)) == 0) 54 | { 55 | sprintf(tmp, ":%u", ntohs(addr.sin_port)); 56 | strcat(str, tmp); 57 | } 58 | else 59 | strcpy(str, "Illegal IPv4 Address"); 60 | return std::string(str); 61 | } 62 | 63 | std::string ip_to_str(const struct sockaddr_in6& addr) 64 | { 65 | char str[112], tmp[16]; 66 | if (uv_ip6_name(const_cast(&addr), str+1, sizeof(str)-1) == 0) 67 | { 68 | str[0] = '['; 69 | sprintf(tmp, "]:%u", ntohs(addr.sin6_port)); 70 | strcat(str, tmp); 71 | } 72 | else 73 | strcpy(str, "Illegal IPv6 Address"); 74 | return std::string(str); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | C_ARGS = -g -Wall -O2 2 | CX = g++ 3 | NO_CHECK = -Ddisable_check_seq_type 4 | 5 | LIB = ../lib/libuv.a ../lib/libccf.a 6 | BIN = test_primitive test_sleep test_udp test_udp2 test_udp3 test_tcp test_tcp2 test_tcp3 unexpected_tcp_timing test_getaddrinfo benchmark_sleep benchmark_udp benchmark_udp2 benchmark_udp2_without_check_seq_type benchmark_tcp benchmark_tcp_without_check_seq_type 7 | 8 | LIB_ARGS = -L../lib -lccf -luv -lpthread -lrt 9 | INC_ARGS = -I../include 10 | 11 | all: $(BIN) 12 | 13 | $(LIB): 14 | make -C ../src/ 15 | 16 | test_primitive: test_primitive.cc $(LIB) 17 | $(CX) $(C_ARGS) -o $@ test_primitive.cc $(LIB_ARGS) $(INC_ARGS) 18 | 19 | test_sleep: test_sleep.cc $(LIB) 20 | $(CX) $(C_ARGS) -o $@ test_sleep.cc $(LIB_ARGS) $(INC_ARGS) 21 | 22 | test_udp: test_udp.cc $(LIB) 23 | $(CX) $(C_ARGS) -o $@ test_udp.cc $(LIB_ARGS) $(INC_ARGS) 24 | 25 | test_udp2: test_udp2.cc $(LIB) 26 | $(CX) $(C_ARGS) -o $@ test_udp2.cc $(LIB_ARGS) $(INC_ARGS) 27 | 28 | test_udp3: test_udp3.cc $(LIB) 29 | $(CX) $(C_ARGS) -o $@ test_udp3.cc $(LIB_ARGS) $(INC_ARGS) 30 | 31 | test_tcp: test_tcp.cc $(LIB) 32 | $(CX) $(C_ARGS) -o $@ test_tcp.cc $(LIB_ARGS) $(INC_ARGS) 33 | 34 | test_tcp2: test_tcp2.cc $(LIB) 35 | $(CX) $(C_ARGS) -o $@ test_tcp2.cc $(LIB_ARGS) $(INC_ARGS) 36 | 37 | test_tcp3: test_tcp3.cc $(LIB) 38 | $(CX) $(C_ARGS) -o $@ test_tcp3.cc $(LIB_ARGS) $(INC_ARGS) 39 | 40 | unexpected_tcp_timing: unexpected_tcp_timing.cc $(LIB) 41 | $(CX) $(C_ARGS) -o $@ unexpected_tcp_timing.cc $(LIB_ARGS) $(INC_ARGS) 42 | 43 | test_getaddrinfo: test_getaddrinfo.cc $(LIB) 44 | $(CX) $(C_ARGS) -o $@ test_getaddrinfo.cc $(LIB_ARGS) $(INC_ARGS) 45 | 46 | benchmark_sleep: benchmark_sleep.cc $(LIB) 47 | $(CX) $(C_ARGS) -o $@ benchmark_sleep.cc $(LIB_ARGS) $(INC_ARGS) 48 | 49 | benchmark_udp: benchmark_udp.cc $(LIB) 50 | $(CX) $(C_ARGS) -o $@ benchmark_udp.cc $(LIB_ARGS) $(INC_ARGS) 51 | 52 | benchmark_udp2: benchmark_udp2.cc $(LIB) 53 | $(CX) $(C_ARGS) -o $@ benchmark_udp2.cc $(LIB_ARGS) $(INC_ARGS) 54 | 55 | benchmark_udp2_without_check_seq_type: benchmark_udp2.cc $(LIB) 56 | $(CX) $(C_ARGS) -o $@ benchmark_udp2.cc $(LIB_ARGS) $(INC_ARGS) $(NO_CHECK) 57 | 58 | benchmark_tcp: benchmark_tcp.cc $(LIB) 59 | $(CX) $(C_ARGS) -o $@ benchmark_tcp.cc $(LIB_ARGS) $(INC_ARGS) 60 | 61 | benchmark_tcp_without_check_seq_type: benchmark_tcp.cc $(LIB) 62 | $(CX) $(C_ARGS) -o $@ benchmark_tcp.cc $(LIB_ARGS) $(INC_ARGS) $(NO_CHECK) 63 | 64 | .PHONY: clean 65 | clean: 66 | rm -f $(BIN) 67 | 68 | .PHONY: test all_test 69 | 70 | test: test_primitive 71 | @(./test_primitive && echo 'Succeed!') || echo 'Failed!' 72 | 73 | all_test: $(BIN) 74 | @echo 'test primitive' 75 | @(./test_primitive && echo 'Succeed') || echo 'Failed' 76 | @echo 'test sleep' 77 | @(./test_sleep > /dev/null && echo 'Succeed') || echo 'Failed' 78 | @echo 'test udp [3]' 79 | @(./test_udp > /dev/null && echo 'Succeed') || echo 'Failed' 80 | @(./test_udp2 > /dev/null && echo 'Succeed') || echo 'Failed' 81 | @(./test_udp3 > /dev/null && echo 'Succeed') || echo 'Failed' 82 | @echo 'test tcp [3]' 83 | @(./test_tcp > /dev/null && echo 'Succeed') || echo 'Failed' 84 | @(./test_tcp2 > /dev/null && echo 'Succeed') || echo 'Failed' 85 | @(./test_tcp3 > /dev/null && echo 'Succeed') || echo 'Failed' 86 | @echo 'test tcp timing' 87 | @(./unexpected_tcp_timing > /dev/null && echo 'Succeed') || echo 'Failed' 88 | @echo 'test getaddrinfo' 89 | @(./test_getaddrinfo > /dev/null && echo 'Succeed') || echo 'Failed' 90 | @echo 'benchmark sleep' 91 | @(./benchmark_sleep > /dev/null && echo 'Succeed') || echo 'Failed' 92 | @echo 'benchmark udp' 93 | @(./benchmark_udp2 > /dev/null && echo 'Succeed') || echo 'Failed' 94 | @echo 'benchmark udp (without check seq type)' 95 | @(./benchmark_udp2_without_check_seq_type > /dev/null && echo 'Succeed') || echo 'Failed' 96 | @echo 'benchmark tcp' 97 | @(./benchmark_tcp > /dev/null && echo 'Succeed') || echo 'Failed' 98 | @echo 'benchmark tcp (without check seq type)' 99 | @(./benchmark_tcp_without_check_seq_type > /dev/null && echo 'Succeed') || echo 'Failed' 100 | -------------------------------------------------------------------------------- /test/benchmark_sleep.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include "cocoflow.h" 7 | 8 | using namespace std; 9 | 10 | #define TEST_TIMES 1000 11 | #define TEST_NUM 1000 12 | 13 | #define ASSERT(x) \ 14 | do { \ 15 | if (!(x)) \ 16 | { \ 17 | fprintf(stderr, "[ASSERT]: " #x " failed at " __FILE__ ":%u\n", __LINE__); \ 18 | abort(); \ 19 | } \ 20 | } while(0) 21 | 22 | static clock_t time_bgn, time_cut, time_end; 23 | 24 | typedef ccf::task<15> test_task; 25 | 26 | class sleep_task: public test_task 27 | { 28 | void run() 29 | { 30 | for (int i=0; istatus() == ccf::ready); 46 | ccf::start(s); 47 | } 48 | } 49 | }; 50 | 51 | int main() 52 | { 53 | time_bgn = clock(); 54 | 55 | ccf::event_task::init(1); 56 | test_task::init(TEST_NUM + 1); 57 | main_task tMain; 58 | 59 | time_cut = clock(); 60 | 61 | ccf::cocoflow(tMain); 62 | 63 | time_end = clock(); 64 | 65 | cout << "Init: " << (time_cut - time_bgn) << endl; 66 | cout << "Proc: " << (time_end - time_cut) << endl; 67 | cout << "Total: " << (time_end - time_bgn) << endl; 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /test/benchmark_tcp.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include "cocoflow.h" 7 | 8 | #include "simple_rand.h" 9 | 10 | using namespace std; 11 | 12 | #define TEST_PORT 31005 13 | #ifdef _WIN32 14 | #define TEST_TIMES 300 //lite 15 | #else 16 | #define TEST_TIMES 6000 17 | #endif 18 | 19 | #ifdef _MSC_VER 20 | #define ENSURE_TIMING 1 //Avoid unexpected tcp timing in Win 21 | #endif 22 | 23 | #define ASSERT(x) \ 24 | do { \ 25 | if (!(x)) \ 26 | { \ 27 | fprintf(stderr, "[ASSERT]: " #x " failed at " __FILE__ ":%u\n", __LINE__); \ 28 | abort(); \ 29 | } \ 30 | } while(0) 31 | 32 | static void my_pkg_seq_unrecv(const void*, size_t, const ccf::uint32&) 33 | { 34 | ASSERT(0); 35 | } 36 | 37 | static void my_pkg_seq_failed(const void*, size_t, int) 38 | { 39 | ASSERT(0); 40 | } 41 | 42 | static clock_t time_bgn, time_cut, time_end; 43 | 44 | typedef ccf::task<15> test_task; 45 | 46 | size_t get_len_from_header(const void* buf, size_t size) 47 | { 48 | if (size < sizeof(ccf::uint32)) 49 | return 0; 50 | const ccf::uint32 *len = (const ccf::uint32 *)buf; 51 | return *len; 52 | } 53 | 54 | int get_seq_from_buf(const void* buf, size_t size, ccf::uint32* seq) 55 | { 56 | if (size < sizeof(ccf::uint32) + sizeof(ccf::uint32)) 57 | return -1; 58 | *seq = ntohl(*(((ccf::uint32*)buf) + 1)); 59 | return 0; 60 | } 61 | 62 | class echo_task: public test_task 63 | { 64 | static int times; 65 | static ccf::tcp::connected tc; 66 | void run() 67 | { 68 | int ret; 69 | char buf[1024]; 70 | size_t len = sizeof(buf); 71 | ccf::tcp::recv tr(ret, echo_task::tc, buf, len); 72 | await(tr); 73 | ASSERT(ret == ccf::tcp::success); 74 | if (++echo_task::times < TEST_TIMES) 75 | { 76 | echo_task* echo = new echo_task(); 77 | ASSERT(echo->status() == ccf::ready); 78 | ccf::start(echo); 79 | } 80 | ccf::tcp::send ts(ret, echo_task::tc, buf, len); 81 | await(ts); 82 | ASSERT(ret == ccf::tcp::success); 83 | } 84 | friend class accept_task; 85 | public: 86 | static void init() 87 | { 88 | ASSERT(echo_task::tc.bind(sizeof(ccf::uint32), 1024, get_len_from_header, get_seq_from_buf, my_pkg_seq_unrecv, my_pkg_seq_failed) == 0); 89 | } 90 | }; 91 | 92 | int echo_task::times = 0; 93 | ccf::tcp::connected echo_task::tc; 94 | 95 | class accept_task: public test_task 96 | { 97 | static ccf::tcp::listening tl; 98 | void run() 99 | { 100 | int ret; 101 | ASSERT(accept_task::tl.bind(ccf::ip_to_addr("0.0.0.0", TEST_PORT)) == 0); 102 | ccf::tcp::accept ta(ret, accept_task::tl, echo_task::tc); 103 | await(ta); 104 | ASSERT(ret == ccf::tcp::success); 105 | echo_task::init(); 106 | ccf::start(new echo_task()); 107 | } 108 | }; 109 | 110 | ccf::tcp::listening accept_task::tl(1); 111 | 112 | class seq_task: public test_task 113 | { 114 | static int times; 115 | static ccf::tcp::connected tc; 116 | ccf::uint32 seq; 117 | void run() 118 | { 119 | int ret0, ret1; 120 | char buf_in[1024], buf_out[1024]; 121 | ccf::uint32 *plen = (ccf::uint32 *)buf_out; 122 | ccf::uint32 *pseq = ((ccf::uint32 *)buf_out) + 1; 123 | *plen = simple_rand()%128 + 8; 124 | *pseq = htonl(this->seq); 125 | size_t len = sizeof(buf_in); 126 | #ifndef ENSURE_TIMING 127 | ccf::tcp::send ts(ret0, seq_task::tc, buf_out, *plen); 128 | await(ts); 129 | ASSERT(ret0 == ccf::tcp::success); 130 | ccf::tcp::recv_by_seq_u32 tr(ret1, seq_task::tc, buf_in, len, this->seq); 131 | await(tr); 132 | ASSERT(ret1 == ccf::tcp::success); 133 | #else 134 | ccf::tcp::send ts(ret0, seq_task::tc, buf_out, *plen); 135 | ccf::tcp::recv_by_seq_u32 tr(ret1, seq_task::tc, buf_in, len, this->seq); 136 | ccf::all_of all(ts, tr); 137 | await(all); 138 | ASSERT(ret0 == ccf::tcp::success); 139 | ASSERT(ret1 == ccf::tcp::success); 140 | #endif 141 | if (++seq_task::times == TEST_TIMES) 142 | { 143 | time_end = clock(); 144 | cout << "Init: " << (time_cut - time_bgn) << endl; 145 | cout << "Proc: " << (time_end - time_cut) << endl; 146 | cout << "Total: " << (time_end - time_bgn) << endl; 147 | exit(0); 148 | } 149 | } 150 | public: 151 | static void init() 152 | { 153 | int ret; 154 | ccf::tcp::connect c(ret, seq_task::tc, ccf::ip_to_addr("127.0.0.1", TEST_PORT)); 155 | await(c); 156 | ASSERT(ret == ccf::tcp::success); 157 | ASSERT(seq_task::tc.bind(sizeof(ccf::uint32), 1024, get_len_from_header, get_seq_from_buf, my_pkg_seq_unrecv, my_pkg_seq_failed) == 0); 158 | } 159 | seq_task(ccf::uint32 seq) : seq(seq) {} 160 | }; 161 | 162 | int seq_task::times = 0; 163 | ccf::tcp::connected seq_task::tc; 164 | 165 | class main_task: public test_task 166 | { 167 | void run() 168 | { 169 | ccf::start(new accept_task()); 170 | seq_task::init(); 171 | for (int i=0; istatus() == ccf::ready); 175 | ccf::start(seq); 176 | } 177 | } 178 | }; 179 | 180 | int main() 181 | { 182 | time_bgn = clock(); 183 | 184 | #ifndef ENSURE_TIMING 185 | ccf::event_task::init(1); 186 | #else 187 | ccf::event_task::init(TEST_TIMES * 2); 188 | #endif 189 | test_task::init(TEST_TIMES * 2 + 1); 190 | main_task tMain; 191 | 192 | time_cut = clock(); 193 | 194 | ccf::cocoflow(tMain); 195 | 196 | return 0; 197 | } 198 | -------------------------------------------------------------------------------- /test/benchmark_udp.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include "cocoflow.h" 7 | 8 | using namespace std; 9 | 10 | #define TEST_PORT 30917 11 | #ifdef _WIN32 12 | #define TEST_TIMES 1000 //lite 13 | #else 14 | #define TEST_TIMES 10000 15 | #endif 16 | 17 | #define ASSERT(x) \ 18 | do { \ 19 | if (!(x)) \ 20 | { \ 21 | fprintf(stderr, "[ASSERT]: " #x " failed at " __FILE__ ":%u\n", __LINE__); \ 22 | abort(); \ 23 | } \ 24 | } while(0) 25 | 26 | static void my_pkg_seq_unrecv(const void*, size_t, const ccf::uint32&) 27 | { 28 | ASSERT(0); 29 | } 30 | 31 | static void my_pkg_seq_failed(const void*, size_t, int) 32 | { 33 | ASSERT(0); 34 | } 35 | 36 | static clock_t time_bgn, time_cut, time_end; 37 | static int sleep_time = 2; 38 | 39 | typedef ccf::task<15> test_task; 40 | 41 | class echo_task: public test_task 42 | { 43 | static int times; 44 | static ccf::udp u; 45 | void run() 46 | { 47 | char buf[4096]; 48 | struct sockaddr_in peer; 49 | size_t len = sizeof(buf); 50 | ccf::udp::recv ur(echo_task::u, buf, len); 51 | await(ur); 52 | ASSERT(ur.peer_type() == AF_INET); 53 | peer = ur.peer_addr_ipv4(); 54 | if (++echo_task::times < TEST_TIMES) 55 | { 56 | echo_task* echo = new echo_task(); 57 | ASSERT(echo->status() == ccf::ready); 58 | ccf::start(echo); 59 | } 60 | ccf::udp::send us(echo_task::u, peer, buf, len); 61 | await(us); 62 | } 63 | public: 64 | static void init() 65 | { 66 | ASSERT(u.bind(ccf::ip_to_addr("0.0.0.0", TEST_PORT)) == 0); 67 | } 68 | }; 69 | 70 | int echo_task::times = 0; 71 | ccf::udp echo_task::u; 72 | 73 | int get_seq_from_buf(const void* buf, size_t size, ccf::uint32* seq) 74 | { 75 | if (size < sizeof(ccf::uint32)) 76 | return -1; 77 | *seq = ntohl(*(ccf::uint32*)buf); 78 | return 0; 79 | } 80 | 81 | class seq_task: public test_task 82 | { 83 | static int times; 84 | static ccf::udp u; 85 | static struct sockaddr_in target; 86 | ccf::uint32 seq; 87 | void run() 88 | { 89 | char buf[4096]; 90 | ccf::uint32 *pos = (ccf::uint32 *)buf; 91 | *pos = htonl(this->seq); 92 | ccf::udp::send us(seq_task::u, seq_task::target, buf, sizeof(ccf::uint32)); 93 | await(us); 94 | size_t len = sizeof(buf); 95 | ccf::udp::recv_by_seq_u32 ur(seq_task::u, buf, len, this->seq); 96 | await(ur); 97 | if (++seq_task::times == TEST_TIMES) 98 | { 99 | time_end = clock(); 100 | cout << "Init: " << (time_cut - time_bgn) << endl; 101 | cout << "Proc: " << (time_end - time_cut) << endl; 102 | cout << "Total: " << (time_end - time_bgn) << endl; 103 | exit(0); 104 | } 105 | } 106 | public: 107 | static void init() 108 | { 109 | seq_task::target = ccf::ip_to_addr("127.0.0.1", TEST_PORT); 110 | ASSERT(seq_task::u.bind(get_seq_from_buf, my_pkg_seq_unrecv, my_pkg_seq_failed) == 0); 111 | } 112 | seq_task(ccf::uint32 seq) : seq(seq) {} 113 | }; 114 | 115 | int seq_task::times = 0; 116 | ccf::udp seq_task::u; 117 | struct sockaddr_in seq_task::target; 118 | 119 | class main_task: public test_task 120 | { 121 | void run() 122 | { 123 | echo_task::init(); 124 | seq_task::init(); 125 | ccf::start(new echo_task()); 126 | for (int i=0; istatus() == ccf::ready); 135 | ccf::start(seq); 136 | } 137 | } 138 | }; 139 | 140 | int main(int argc, char* argv[]) 141 | { 142 | if (argc > 1) 143 | sleep_time = atoi(argv[1]); 144 | 145 | time_bgn = clock(); 146 | 147 | ccf::event_task::init(1); 148 | test_task::init(TEST_TIMES + 101); 149 | main_task tMain; 150 | 151 | time_cut = clock(); 152 | 153 | ccf::cocoflow(tMain); 154 | 155 | return 0; 156 | } 157 | -------------------------------------------------------------------------------- /test/benchmark_udp2.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | 6 | #include "cocoflow.h" 7 | 8 | using namespace std; 9 | 10 | #define TEST_PORT 30917 11 | #ifdef _WIN32 12 | #define TEST_TIMES 1000 //lite 13 | #else 14 | #define TEST_TIMES 10000 15 | #endif 16 | 17 | #define ASSERT(x) \ 18 | do { \ 19 | if (!(x)) \ 20 | { \ 21 | fprintf(stderr, "[ASSERT]: " #x " failed at " __FILE__ ":%u\n", __LINE__); \ 22 | abort(); \ 23 | } \ 24 | } while(0) 25 | 26 | static void my_pkg_seq_unrecv(const void*, size_t, const ccf::uint32&) 27 | { 28 | ASSERT(0); 29 | } 30 | 31 | static void my_pkg_seq_failed(const void*, size_t, int) 32 | { 33 | ASSERT(0); 34 | } 35 | 36 | static clock_t time_bgn, time_cut, time_end; 37 | 38 | typedef ccf::task<15> test_task; 39 | 40 | class echo_task: public test_task 41 | { 42 | static int times; 43 | static ccf::udp u; 44 | void run() 45 | { 46 | char buf[4096]; 47 | struct sockaddr_in peer; 48 | size_t len = sizeof(buf); 49 | ccf::udp::recv ur(echo_task::u, buf, len); 50 | await(ur); 51 | ASSERT(ur.peer_type() == AF_INET); 52 | peer = ur.peer_addr_ipv4(); 53 | if (++echo_task::times < TEST_TIMES) 54 | { 55 | echo_task* echo = new echo_task(); 56 | ASSERT(echo->status() == ccf::ready); 57 | ccf::start(echo); 58 | } 59 | ccf::udp::send us(echo_task::u, peer, buf, len); 60 | await(us); 61 | } 62 | public: 63 | static void init() 64 | { 65 | ASSERT(u.bind(ccf::ip_to_addr("0.0.0.0", TEST_PORT)) == 0); 66 | } 67 | }; 68 | 69 | int echo_task::times = 0; 70 | ccf::udp echo_task::u; 71 | 72 | int get_seq_from_buf(const void* buf, size_t size, ccf::uint32* seq) 73 | { 74 | if (size < sizeof(ccf::uint32)) 75 | return -1; 76 | *seq = ntohl(*(ccf::uint32*)buf); 77 | return 0; 78 | } 79 | 80 | class seq_task: public test_task 81 | { 82 | static int times; 83 | static ccf::udp u; 84 | static struct sockaddr_in target; 85 | ccf::uint32 seq; 86 | void run() 87 | { 88 | char buf[4096]; 89 | ccf::uint32 *pos = (ccf::uint32 *)buf; 90 | *pos = htonl(this->seq); 91 | ccf::udp::send us(seq_task::u, seq_task::target, buf, sizeof(ccf::uint32)); 92 | await(us); 93 | size_t len = sizeof(buf); 94 | ccf::udp::recv_by_seq_u32 ur(seq_task::u, buf, len, this->seq); 95 | await(ur); 96 | if (++seq_task::times == TEST_TIMES) 97 | { 98 | time_end = clock(); 99 | cout << "Init: " << (time_cut - time_bgn) << endl; 100 | cout << "Proc: " << (time_end - time_cut) << endl; 101 | cout << "Total: " << (time_end - time_bgn) << endl; 102 | exit(0); 103 | } 104 | if ((seq_task::times+1)%100 == 99) 105 | ccf::sync::notify(0l); 106 | } 107 | public: 108 | static void init() 109 | { 110 | seq_task::target = ccf::ip_to_addr("127.0.0.1", TEST_PORT); 111 | ASSERT(seq_task::u.bind(get_seq_from_buf, my_pkg_seq_unrecv, my_pkg_seq_failed) == 0); 112 | } 113 | seq_task(ccf::uint32 seq) : seq(seq) {} 114 | }; 115 | 116 | int seq_task::times = 0; 117 | ccf::udp seq_task::u; 118 | struct sockaddr_in seq_task::target; 119 | 120 | class main_task: public test_task 121 | { 122 | void run() 123 | { 124 | echo_task::init(); 125 | seq_task::init(); 126 | ccf::start(new echo_task()); 127 | for (int i=0; istatus() == ccf::ready); 136 | ccf::start(seq); 137 | } 138 | } 139 | }; 140 | 141 | int main() 142 | { 143 | time_bgn = clock(); 144 | 145 | ccf::event_task::init(1); 146 | test_task::init(TEST_TIMES + 101); 147 | main_task tMain; 148 | 149 | time_cut = clock(); 150 | 151 | ccf::cocoflow(tMain); 152 | 153 | return 0; 154 | } 155 | -------------------------------------------------------------------------------- /test/simple_rand.h: -------------------------------------------------------------------------------- 1 | #ifndef __SIMPLE_RAMD_H__ 2 | #define __SIMPLE_RAMD_H__ 3 | 4 | /* Just to remove the platform differences */ 5 | static int simple_rand() 6 | { 7 | static unsigned long seed = 404264294; 8 | return (((seed = seed * 214013L + 2531011L) >> 16) & 0x7fff); 9 | } 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /test/test_getaddrinfo.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "cocoflow.h" 4 | 5 | using namespace std; 6 | 7 | void show(int ret, struct addrinfo *result, const char *errmsg) 8 | { 9 | if (ret) 10 | { 11 | if (errmsg) 12 | cout << "getaddrinfo: " << ret << " " << errmsg << endl; 13 | else 14 | cout << "getaddrinfo: " << ret << endl; 15 | } 16 | else 17 | { 18 | cout << "getaddrinfo:" << endl; 19 | struct addrinfo *cur = result; 20 | while (cur) 21 | { 22 | cout << " " << ccf::ip_to_str(cur->ai_addr) << endl; 23 | cur = cur->ai_next; 24 | } 25 | ccf::getaddrinfo::freeaddrinfo(result); 26 | } 27 | } 28 | 29 | class main_task: public ccf::user_task 30 | { 31 | void run() 32 | { 33 | int ret; 34 | struct addrinfo *result; 35 | const char *errmsg; 36 | 37 | ccf::getaddrinfo server(ret, &result, &errmsg, NULL, "ssh"); 38 | await(server); 39 | show(ret, result, errmsg); 40 | 41 | ccf::getaddrinfo dns(ret, &result, &errmsg, "localhost", NULL); 42 | await(dns); 43 | show(ret, result, errmsg); 44 | 45 | ccf::getaddrinfo dns2(ret, &result, &errmsg, "www.qq.com", NULL); 46 | await(dns2); 47 | show(ret, result, errmsg); 48 | 49 | ccf::getaddrinfo dns3(ret, &result, &errmsg, "127.0.0.1", NULL); 50 | await(dns3); 51 | show(ret, result, errmsg); 52 | 53 | ccf::getaddrinfo none(ret, &result, &errmsg, NULL, NULL); 54 | await(none); 55 | show(ret, result, errmsg); 56 | 57 | ccf::getaddrinfo dns4(ret, &result, &errmsg, "www.qq.com", NULL); 58 | ccf::sleep s(0); 59 | ccf::any_of any(dns4, s); 60 | await(any); 61 | show(ret, result, errmsg); 62 | } 63 | }; 64 | 65 | int main() 66 | { 67 | ccf::event_task::init(100); 68 | ccf::user_task::init(100); 69 | 70 | //ccf::set_debug(stderr); 71 | 72 | main_task tMain; 73 | ccf::cocoflow(tMain); 74 | return 0; 75 | } 76 | -------------------------------------------------------------------------------- /test/test_sleep.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "cocoflow.h" 4 | 5 | using namespace std; 6 | 7 | class test_task: public ccf::user_task 8 | { 9 | int id; 10 | void run() 11 | { 12 | cout << this->id << " await sleep(3000)" << endl; 13 | ccf::sleep s1(1000), s2(2000); 14 | await(s1); 15 | await(s2); 16 | cout << this->id << " await End" << endl; 17 | } 18 | public: 19 | test_task(int id):id(id){} 20 | }; 21 | 22 | class main_task: public ccf::user_task 23 | { 24 | void run() 25 | { 26 | cout << "await test_task(0:new)" << endl; 27 | test_task tt(0); 28 | await(tt); 29 | cout << "start test_task(0:end, 1:new)" << endl; 30 | ccf::start(new test_task(1)); 31 | cout << "start test_task(1:end, 2:new)" << endl; 32 | ccf::start(new test_task(2)); 33 | cout << "start test_task(2:end, 3:new)" << endl; 34 | ccf::start(new test_task(3)); 35 | cout << "start test_task(3:end, 4:new)" << endl; 36 | ccf::start(new test_task(4)); 37 | cout << "start test_task(4:end)" << endl; 38 | } 39 | }; 40 | 41 | int main() 42 | { 43 | ccf::event_task::init(100); 44 | ccf::user_task::init(100); 45 | 46 | //ccf::set_debug(stderr); 47 | 48 | main_task tMain; 49 | ccf::cocoflow(tMain); 50 | return 0; 51 | } 52 | -------------------------------------------------------------------------------- /test/test_tcp.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "cocoflow.h" 6 | 7 | #include "simple_rand.h" 8 | 9 | using namespace std; 10 | 11 | #define TEST_PORT 31005 12 | #define TEST_TIMES 10 13 | #define TEST_LEN 16 14 | 15 | #define ASSERT(x) \ 16 | do { \ 17 | if (!(x)) \ 18 | { \ 19 | fprintf(stderr, "[ASSERT]: " #x " failed at " __FILE__ ":%u\n", __LINE__); \ 20 | abort(); \ 21 | } \ 22 | } while(0) 23 | 24 | class recv_task: public ccf::user_task 25 | { 26 | void run() 27 | { 28 | int ret; 29 | ccf::tcp::listening tl(1); 30 | ASSERT(tl.bind(ccf::ip_to_addr("0.0.0.0", TEST_PORT)) == 0); 31 | ccf::tcp::connected tc; 32 | ccf::tcp::accept ta(ret, tl, tc); 33 | await(ta); 34 | ASSERT(ret == ccf::tcp::success); 35 | size_t total_len = 0; 36 | for (;;) 37 | { 38 | char buf[64]; 39 | ccf::sleep s(simple_rand()%5000); 40 | await(s); 41 | size_t len = sizeof(buf); 42 | ccf::tcp::recv tr(ret, tc, buf, len); 43 | await(tr); 44 | ASSERT(ret == ccf::tcp::success); 45 | cout << "server recv " << len << endl; 46 | total_len += len; 47 | if (total_len == TEST_TIMES * TEST_LEN) 48 | break; 49 | } 50 | } 51 | }; 52 | 53 | class send_task: public ccf::user_task 54 | { 55 | void run() 56 | { 57 | int ret; 58 | ccf::tcp::connected tc; 59 | ccf::tcp::connect c(ret, tc, ccf::ip_to_addr("127.0.0.1", TEST_PORT)); 60 | await(c); 61 | ASSERT(ret == ccf::tcp::success); 62 | for (int i=0; i 2 | 3 | #include 4 | 5 | #include "cocoflow.h" 6 | 7 | using namespace std; 8 | 9 | #define TEST_PORT 31005 10 | 11 | #define ASSERT(x) \ 12 | do { \ 13 | if (!(x)) \ 14 | { \ 15 | fprintf(stderr, "[ASSERT]: " #x " failed at " __FILE__ ":%u\n", __LINE__); \ 16 | abort(); \ 17 | } \ 18 | } while(0) 19 | 20 | class recv_task: public ccf::user_task 21 | { 22 | void run() 23 | { 24 | int ret; 25 | char buf[64]; 26 | ccf::tcp::listening tl(1); 27 | ASSERT(tl.bind(ccf::ip_to_addr("0.0.0.0", TEST_PORT)) == 0); 28 | ccf::tcp::connected tc; 29 | ccf::tcp::accept ta(ret, tl, tc); 30 | await(ta); 31 | ASSERT(ret == ccf::tcp::success); 32 | size_t len = sizeof(buf); 33 | ccf::sleep s(500); 34 | ccf::tcp::recv_till tr0(ret, tc, buf, len); 35 | ccf::any_of any(tr0, s); 36 | await(any); 37 | ASSERT(ret == ccf::tcp::unfinished); 38 | if (any.who_completed() == 1) 39 | cout << "server cancel recv " << len << endl; 40 | len = 20; 41 | ccf::tcp::recv_till tr1(ret, tc, buf, len); 42 | await(tr1); 43 | ASSERT(ret == ccf::tcp::success); 44 | cout << "server recv " << len << endl; 45 | ccf::tcp::recv_till tr2(ret, tc, buf, len, "!!", 2); 46 | await(tr2); 47 | ASSERT(ret == ccf::tcp::success); 48 | cout << "server recv " << len << endl; 49 | } 50 | }; 51 | 52 | class send_task: public ccf::user_task 53 | { 54 | void run() 55 | { 56 | int ret; 57 | char buf[64] = "hello world!!"; 58 | ccf::tcp::connected tc; 59 | ccf::tcp::connect c(ret, tc, ccf::ip_to_addr("127.0.0.1", TEST_PORT)); 60 | await(c); 61 | ASSERT(ret == ccf::tcp::success); 62 | ccf::tcp::send ts0(ret, tc, buf, 20); 63 | await(ts0); 64 | ASSERT(ret == ccf::tcp::success); 65 | cout << "client send 20" << endl; 66 | ccf::sleep s(1000); 67 | await(s); 68 | ccf::tcp::send ts1(ret, tc, buf, 20); 69 | await(ts1); 70 | ASSERT(ret == ccf::tcp::success); 71 | cout << "client send 20" << endl; 72 | } 73 | }; 74 | 75 | class main_task: public ccf::user_task 76 | { 77 | void run() 78 | { 79 | ccf::start(new recv_task()); 80 | ccf::start(new send_task()); 81 | } 82 | }; 83 | 84 | int main() 85 | { 86 | ccf::event_task::init(100); 87 | ccf::user_task::init(100); 88 | 89 | //ccf::set_debug(stderr); 90 | 91 | main_task tMain; 92 | ccf::cocoflow(tMain); 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /test/test_tcp3.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | #include "cocoflow.h" 6 | 7 | #include "simple_rand.h" 8 | 9 | using namespace std; 10 | 11 | #define TEST_PORT 31005 12 | #define TEST_TIMES 10 13 | 14 | #define ASSERT(x) \ 15 | do { \ 16 | if (!(x)) \ 17 | { \ 18 | fprintf(stderr, "[ASSERT]: " #x " failed at " __FILE__ ":%u\n", __LINE__); \ 19 | abort(); \ 20 | } \ 21 | } while(0) 22 | 23 | size_t get_len_from_header(const void* buf, size_t size) 24 | { 25 | if (size < sizeof(ccf::uint32)) 26 | return 0; 27 | const ccf::uint32 *len = (const ccf::uint32 *)buf; 28 | return *len; 29 | } 30 | 31 | int get_seq_from_buf(const void* buf, size_t size, ccf::uint32* seq) 32 | { 33 | if (size < sizeof(ccf::uint32) + sizeof(ccf::uint32)) 34 | return -1; 35 | *seq = ntohl(*(((ccf::uint32*)buf) + 1)); 36 | return 0; 37 | } 38 | 39 | class echo_task: public ccf::user_task 40 | { 41 | static int times; 42 | static ccf::tcp::connected tc; 43 | void run() 44 | { 45 | int ret; 46 | char buf[1024]; 47 | size_t len = sizeof(buf); 48 | ccf::uint64 t = simple_rand()%10000; 49 | ccf::tcp::recv tr(ret, echo_task::tc, buf, len); 50 | await(tr); 51 | ASSERT(ret == ccf::tcp::success); 52 | if (++echo_task::times < TEST_TIMES) 53 | ccf::start(new echo_task()); 54 | cout << "echo_task recv " << len << endl; 55 | cout << "echo_task sleep " << t << endl; 56 | ccf::sleep s(t); 57 | await(s); 58 | ccf::tcp::send ts(ret, echo_task::tc, buf, len); 59 | await(ts); 60 | ASSERT(ret == ccf::tcp::success); 61 | cout << "echo_task send " << len << endl; 62 | } 63 | friend class accept_task; 64 | public: 65 | static void init() 66 | { 67 | ASSERT(echo_task::tc.bind(sizeof(ccf::uint32), 1024, get_len_from_header, get_seq_from_buf) == 0); 68 | } 69 | }; 70 | 71 | int echo_task::times = 0; 72 | ccf::tcp::connected echo_task::tc; 73 | 74 | class accept_task: public ccf::user_task 75 | { 76 | static ccf::tcp::listening tl; 77 | void run() 78 | { 79 | int ret; 80 | ASSERT(accept_task::tl.bind(ccf::ip_to_addr("0.0.0.0", TEST_PORT)) == 0); 81 | ccf::tcp::accept ta(ret, accept_task::tl, echo_task::tc); 82 | await(ta); 83 | ASSERT(ret == ccf::tcp::success); 84 | echo_task::init(); 85 | ccf::start(new echo_task()); 86 | } 87 | }; 88 | 89 | ccf::tcp::listening accept_task::tl(1); 90 | 91 | class seq_task: public ccf::user_task 92 | { 93 | static int times; 94 | static ccf::tcp::connected tc; 95 | ccf::uint32 seq; 96 | void run() 97 | { 98 | int ret; 99 | char buf[1024]; 100 | ccf::uint32 *plen = (ccf::uint32 *)buf; 101 | ccf::uint32 *pseq = ((ccf::uint32 *)buf) + 1; 102 | *plen = simple_rand()%512 + 8; 103 | *pseq = htonl(this->seq); 104 | ccf::tcp::send ts(ret, seq_task::tc, buf, *plen); 105 | await(ts); 106 | ASSERT(ret == ccf::tcp::success); 107 | cout << "seq_task send " << *plen << ", seq = " << this->seq << endl; 108 | size_t len = sizeof(buf); 109 | ccf::tcp::recv_by_seq_u32 tr(ret, seq_task::tc, buf, len, this->seq); 110 | await(tr); 111 | ASSERT(ret == ccf::tcp::success); 112 | cout << "seq_task recv " << len << ", seq = " << this->seq << endl; 113 | if (++seq_task::times == TEST_TIMES) 114 | exit(0); 115 | } 116 | public: 117 | static void init() 118 | { 119 | int ret; 120 | ccf::tcp::connect c(ret, seq_task::tc, ccf::ip_to_addr("127.0.0.1", TEST_PORT)); 121 | await(c); 122 | ASSERT(ret == ccf::tcp::success); 123 | ASSERT(seq_task::tc.bind(sizeof(ccf::uint32), 1024, get_len_from_header, get_seq_from_buf) == 0); 124 | } 125 | seq_task(ccf::uint32 seq) : seq(seq) {} 126 | }; 127 | 128 | int seq_task::times = 0; 129 | ccf::tcp::connected seq_task::tc; 130 | 131 | class main_task: public ccf::user_task 132 | { 133 | void run() 134 | { 135 | ccf::start(new accept_task()); 136 | seq_task::init(); 137 | for (int i=0; i 2 | 3 | #include 4 | 5 | #include "cocoflow.h" 6 | 7 | using namespace std; 8 | 9 | #define TEST_PORT 30917 10 | #define TEST_TIMES 10 11 | 12 | #define ASSERT(x) \ 13 | do { \ 14 | if (!(x)) \ 15 | { \ 16 | fprintf(stderr, "[ASSERT]: " #x " failed at " __FILE__ ":%u\n", __LINE__); \ 17 | abort(); \ 18 | } \ 19 | } while(0) 20 | 21 | class recv_task: public ccf::user_task 22 | { 23 | void run() 24 | { 25 | ccf::udp u; 26 | char buf[65536]; 27 | ASSERT(u.bind(ccf::ip_to_addr("0.0.0.0", TEST_PORT)) == 0); 28 | for (int i=0; i 2 | 3 | #include 4 | 5 | #include "cocoflow.h" 6 | 7 | #include "simple_rand.h" 8 | 9 | using namespace std; 10 | 11 | #define TEST_PORT 30917 12 | #define TEST_TIMES 10 13 | 14 | #define ASSERT(x) \ 15 | do { \ 16 | if (!(x)) \ 17 | { \ 18 | fprintf(stderr, "[ASSERT]: " #x " failed at " __FILE__ ":%u\n", __LINE__); \ 19 | abort(); \ 20 | } \ 21 | } while(0) 22 | 23 | class echo_task: public ccf::user_task 24 | { 25 | void run() 26 | { 27 | ccf::udp u; 28 | char buf[65536]; 29 | struct sockaddr_in peer; 30 | ASSERT(u.bind(ccf::ip_to_addr("0.0.0.0", TEST_PORT)) == 0); 31 | for (int i=0; iy; 29 | } 30 | }; 31 | 32 | class echo_task: public ccf::user_task 33 | { 34 | static int times; 35 | static ccf::udp u; 36 | void run() 37 | { 38 | char buf[65536]; 39 | struct sockaddr_in peer; 40 | size_t len = sizeof(buf); 41 | ccf::uint64 t = simple_rand()%10000; 42 | ccf::udp::recv ur(echo_task::u, buf, len); 43 | await(ur); 44 | ASSERT(ur.peer_type() == AF_INET); 45 | peer = ur.peer_addr_ipv4(); 46 | if (++echo_task::times < TEST_TIMES) 47 | ccf::start(new echo_task()); 48 | cout << "echo_task recv " << len << " from " << ccf::ip_to_str(peer) << endl; 49 | cout << "echo_task sleep " << t << endl; 50 | ccf::sleep s(t); 51 | await(s); 52 | ccf::udp::send us(echo_task::u, peer, buf, len); 53 | await(us); 54 | cout << "echo_task send " << len << " to " << ccf::ip_to_str(peer) << endl; 55 | } 56 | public: 57 | static void init() 58 | { 59 | ASSERT(u.bind(ccf::ip_to_addr("0.0.0.0", TEST_PORT)) == 0); 60 | } 61 | }; 62 | 63 | int echo_task::times = 0; 64 | ccf::udp echo_task::u; 65 | 66 | int get_seq_from_buf(const void* buf, size_t size, ccf::uint32* seq) 67 | { 68 | if (size < sizeof(ccf::uint32)) 69 | return -1; 70 | *seq = ntohl(*(ccf::uint32*)buf); 71 | return 0; 72 | } 73 | 74 | class seq_task: public ccf::user_task 75 | { 76 | static int times; 77 | static ccf::udp u; 78 | static struct sockaddr_in target; 79 | ccf::uint32 seq; 80 | void run() 81 | { 82 | char buf[65536]; 83 | ccf::uint32 *pos = (ccf::uint32 *)buf; 84 | *pos = htonl(this->seq); 85 | int add_len = simple_rand()%100; 86 | ccf::udp::send us(seq_task::u, seq_task::target, buf, sizeof(ccf::uint32) + add_len); 87 | await(us); 88 | cout << "seq_task send " << sizeof(ccf::uint32) + add_len << ", seq = " << this->seq << endl; 89 | size_t len = sizeof(buf); 90 | ccf::udp::recv_by_seq_u32 ur(seq_task::u, buf, len, this->seq); 91 | await(ur); 92 | cout << "seq_task recv " << len << ", seq = " << this->seq << endl; 93 | if (++seq_task::times == TEST_TIMES) 94 | exit(0); 95 | } 96 | public: 97 | static void init() 98 | { 99 | seq_task::target = ccf::ip_to_addr("127.0.0.1", TEST_PORT); 100 | ASSERT(seq_task::u.bind(get_seq_from_buf) == 0); 101 | } 102 | seq_task(ccf::uint32 seq) : seq(seq) {} 103 | }; 104 | 105 | int seq_task::times = 0; 106 | ccf::udp seq_task::u; 107 | struct sockaddr_in seq_task::target; 108 | 109 | class main_task: public ccf::user_task 110 | { 111 | void run() 112 | { 113 | echo_task::init(); 114 | seq_task::init(); 115 | ccf::start(new echo_task()); 116 | for (int i=0; i 2 | #include 3 | #include 4 | 5 | #define TEST_TIMES 100000 6 | 7 | ucontext_t ucs[2]; 8 | 9 | char sBufs[TEST_TIMES][2048]; 10 | 11 | void ping() 12 | { 13 | } 14 | 15 | int main() 16 | { 17 | int i; 18 | clock_t tBgn, tEnd; 19 | 20 | tBgn = clock(); 21 | 22 | for (i=0; i 2 | #include 3 | #include 4 | 5 | #define TEST_TIMES 100000 6 | 7 | ucontext_t ucs[TEST_TIMES + 1]; 8 | 9 | char sBufs[TEST_TIMES][4096]; 10 | 11 | void ping() 12 | { 13 | } 14 | 15 | int main() 16 | { 17 | int i; 18 | clock_t tBgn, tEnd, tBrk1, tBrk2, tBrk3; 19 | 20 | tBgn = clock(); 21 | 22 | for (i=0; i 2 | #include 3 | #include 4 | 5 | #define TEST_TIMES 100000 6 | 7 | ucontext_t ucs[TEST_TIMES + 1]; 8 | 9 | char sBufs[TEST_TIMES][2048]; 10 | 11 | void ping() 12 | { 13 | } 14 | 15 | int main() 16 | { 17 | int i; 18 | clock_t tBgn, tEnd, tBrk1, tBrk2, tBrk3; 19 | 20 | tBgn = clock(); 21 | 22 | for (i=0; i 2 | #include 3 | #include 4 | 5 | #define TEST_TIMES 100000 6 | 7 | ucontext_t ucs[TEST_TIMES + 1]; 8 | 9 | char sBufs[TEST_TIMES][512]; 10 | 11 | void ping() 12 | { 13 | } 14 | 15 | int main() 16 | { 17 | int i; 18 | clock_t tBgn, tEnd, tBrk1, tBrk2, tBrk3; 19 | 20 | tBgn = clock(); 21 | 22 | for (i=0; i 2 | #include 3 | #include 4 | 5 | #define TEST_TIMES 100000 6 | 7 | ucontext_t ucs[TEST_TIMES + 1]; 8 | 9 | char sBufs[TEST_TIMES][32768]; 10 | 11 | void ping() 12 | { 13 | } 14 | 15 | int main() 16 | { 17 | int i; 18 | clock_t tBgn, tEnd, tBrk1, tBrk2, tBrk3; 19 | 20 | tBgn = clock(); 21 | 22 | for (i=0; i 2 | #include 3 | #include 4 | 5 | #define TEST_TIMES 100000 6 | 7 | ucontext_t ucs[3]; 8 | 9 | char sBuf1[4096]; 10 | char sBuf2[4096]; 11 | 12 | void ping() 13 | { 14 | int i; 15 | for (i=0; i 2 | #include 3 | #include 4 | 5 | #define TEST_TIMES 100000 6 | 7 | ucontext_t ucs[2]; 8 | 9 | char sBuf[4096]; 10 | 11 | void ping() 12 | { 13 | } 14 | 15 | int main() 16 | { 17 | int i; 18 | clock_t tBgn, tEnd; 19 | 20 | tBgn = clock(); 21 | 22 | for (i=0; i 2 | 3 | #include "cocoflow.h" 4 | 5 | using namespace std; 6 | 7 | #define TEST_PORT 31005 8 | #ifdef _WIN32 9 | #define TEST_TIMES 1000 //lite 10 | #else 11 | #define TEST_TIMES 10000 12 | #endif 13 | #define TEST_SIZE 800 14 | 15 | #define ASSERT(x) \ 16 | do { \ 17 | if (!(x)) \ 18 | { \ 19 | fprintf(stderr, "[ASSERT]: " #x " failed at " __FILE__ ":%u\n", __LINE__); \ 20 | abort(); \ 21 | } \ 22 | } while(0) 23 | 24 | typedef ccf::task<15> test_task; 25 | 26 | static int recv_bytes = 0, send_bytes = 0; 27 | 28 | class recv_task: public test_task 29 | { 30 | void run() 31 | { 32 | int ret; 33 | ccf::tcp::listening tl(1); 34 | ccf::tcp::connected tc; 35 | ASSERT(tl.bind(ccf::ip_to_addr("0.0.0.0", TEST_PORT)) == 0); 36 | ccf::tcp::accept ta(ret, tl, tc); 37 | await(ta); 38 | ASSERT(ret == ccf::tcp::success); 39 | for (;;) 40 | { 41 | char buf[8192]; 42 | size_t len = sizeof(buf); 43 | ccf::tcp::recv tr(ret, tc, buf, len); 44 | await(tr); 45 | ASSERT(ret == ccf::tcp::success); 46 | recv_bytes += len; 47 | if (recv_bytes > send_bytes) 48 | cout << "recv(" << recv_bytes << ") > send(" << send_bytes << ")" << endl; 49 | if (recv_bytes == TEST_TIMES * TEST_SIZE) 50 | exit(0); 51 | } 52 | } 53 | }; 54 | 55 | class send_task: public test_task 56 | { 57 | static ccf::tcp::connected tc; 58 | void run() 59 | { 60 | int ret; 61 | char buf[TEST_SIZE]; 62 | ccf::tcp::send ts(ret, send_task::tc, buf, sizeof(buf)); 63 | await(ts); 64 | ASSERT(ret == ccf::tcp::success); 65 | send_bytes += sizeof(buf); 66 | } 67 | public: 68 | static void init() 69 | { 70 | int ret; 71 | ccf::tcp::connect c(ret, send_task::tc, ccf::ip_to_addr("127.0.0.1", TEST_PORT)); 72 | await(c); 73 | ASSERT(ret == ccf::tcp::success); 74 | } 75 | }; 76 | 77 | ccf::tcp::connected send_task::tc; 78 | 79 | class main_task: public test_task 80 | { 81 | void run() 82 | { 83 | ccf::start(new recv_task()); 84 | send_task::init(); 85 | for (int i=0; istatus() == ccf::ready); 89 | ccf::start(st); 90 | } 91 | } 92 | }; 93 | 94 | int main() 95 | { 96 | ccf::event_task::init(1); 97 | test_task::init(TEST_TIMES + 2); 98 | main_task tMain; 99 | 100 | ccf::cocoflow(tMain); 101 | 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /vc/benchmark_tcp.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 28 | 31 | 34 | 37 | 40 | 43 | 53 | 56 | 59 | 62 | 70 | 73 | 76 | 79 | 82 | 85 | 88 | 91 | 92 | 100 | 103 | 106 | 109 | 112 | 115 | 125 | 128 | 131 | 134 | 144 | 147 | 150 | 153 | 156 | 159 | 162 | 165 | 166 | 173 | 176 | 179 | 182 | 185 | 189 | 199 | 202 | 205 | 208 | 216 | 219 | 222 | 225 | 228 | 231 | 234 | 237 | 238 | 246 | 249 | 252 | 255 | 258 | 262 | 272 | 275 | 278 | 281 | 291 | 294 | 297 | 300 | 303 | 306 | 309 | 312 | 313 | 314 | 315 | 316 | 317 | 322 | 325 | 326 | 327 | 332 | 333 | 338 | 339 | 340 | 341 | 342 | 343 | -------------------------------------------------------------------------------- /vc/benchmark_udp.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 28 | 31 | 34 | 37 | 40 | 43 | 53 | 56 | 59 | 62 | 70 | 73 | 76 | 79 | 82 | 85 | 88 | 91 | 92 | 100 | 103 | 106 | 109 | 112 | 115 | 125 | 128 | 131 | 134 | 144 | 147 | 150 | 153 | 156 | 159 | 162 | 165 | 166 | 173 | 176 | 179 | 182 | 185 | 189 | 199 | 202 | 205 | 208 | 216 | 219 | 222 | 225 | 228 | 231 | 234 | 237 | 238 | 246 | 249 | 252 | 255 | 258 | 262 | 272 | 275 | 278 | 281 | 291 | 294 | 297 | 300 | 303 | 306 | 309 | 312 | 313 | 314 | 315 | 316 | 317 | 322 | 325 | 326 | 327 | 332 | 333 | 338 | 339 | 340 | 341 | 342 | 343 | -------------------------------------------------------------------------------- /vc/demo_all_sort.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 28 | 31 | 34 | 37 | 40 | 43 | 53 | 56 | 59 | 62 | 70 | 73 | 76 | 79 | 82 | 85 | 88 | 91 | 92 | 100 | 103 | 106 | 109 | 112 | 115 | 125 | 128 | 131 | 134 | 144 | 147 | 150 | 153 | 156 | 159 | 162 | 165 | 166 | 173 | 176 | 179 | 182 | 185 | 189 | 199 | 202 | 205 | 208 | 216 | 219 | 222 | 225 | 228 | 231 | 234 | 237 | 238 | 246 | 249 | 252 | 255 | 258 | 262 | 272 | 275 | 278 | 281 | 291 | 294 | 297 | 300 | 303 | 306 | 309 | 312 | 313 | 314 | 315 | 316 | 317 | 322 | 325 | 326 | 327 | 332 | 333 | 338 | 339 | 340 | 341 | 342 | 343 | -------------------------------------------------------------------------------- /vc/libccf.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 15 | 18 | 19 | 20 | 21 | 22 | 29 | 32 | 35 | 38 | 41 | 44 | 57 | 60 | 63 | 66 | 69 | 72 | 75 | 78 | 81 | 84 | 85 | 93 | 96 | 99 | 102 | 105 | 108 | 118 | 121 | 124 | 127 | 130 | 133 | 136 | 139 | 142 | 145 | 146 | 153 | 156 | 159 | 162 | 165 | 169 | 182 | 185 | 188 | 191 | 194 | 197 | 200 | 203 | 206 | 209 | 210 | 218 | 221 | 224 | 227 | 230 | 234 | 244 | 247 | 250 | 253 | 256 | 259 | 262 | 265 | 268 | 271 | 272 | 273 | 274 | 275 | 276 | 281 | 284 | 285 | 288 | 289 | 292 | 293 | 296 | 297 | 300 | 301 | 304 | 305 | 308 | 309 | 310 | 315 | 316 | 321 | 322 | 323 | 324 | 325 | 326 | -------------------------------------------------------------------------------- /vc/test.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | cd %~dp0 4 | 5 | cd Release 6 | 7 | echo test primitive 8 | (test_primitive && echo Succeed) || echo Failed 9 | echo test sleep 10 | (test_sleep > nul && echo Succeed) || echo Failed 11 | echo test udp [3] 12 | (test_udp > nul && echo Succeed) || echo Failed 13 | (test_udp2 > nul && echo Succeed) || echo Failed 14 | (test_udp3 > nul && echo Succeed) || echo Failed 15 | echo test tcp [3] 16 | (test_tcp > nul && echo Succeed) || echo Failed 17 | (test_tcp2 > nul && echo Succeed) || echo Failed 18 | (test_tcp3 > nul && echo Succeed) || echo Failed 19 | echo test tcp timing (lite) 20 | (unexpected_tcp_timing > nul && echo Succeed) || echo Failed 21 | echo test getaddrinfo 22 | (test_getaddrinfo > nul && echo Succeed) || echo Failed 23 | echo benchmark sleep 24 | (benchmark_sleep > nul && echo Succeed) || echo Failed 25 | echo benchmark udp (lite) 26 | (benchmark_udp2 > nul && echo Succeed) || echo Failed 27 | echo benchmark tcp (lite) 28 | (benchmark_tcp > nul && echo Succeed) || echo Failed 29 | 30 | pause 31 | -------------------------------------------------------------------------------- /vc/test_sleep.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 28 | 31 | 34 | 37 | 40 | 43 | 53 | 56 | 59 | 62 | 70 | 73 | 76 | 79 | 82 | 85 | 88 | 91 | 92 | 100 | 103 | 106 | 109 | 112 | 115 | 125 | 128 | 131 | 134 | 144 | 147 | 150 | 153 | 156 | 159 | 162 | 165 | 166 | 173 | 176 | 179 | 182 | 185 | 189 | 199 | 202 | 205 | 208 | 216 | 219 | 222 | 225 | 228 | 231 | 234 | 237 | 238 | 246 | 249 | 252 | 255 | 258 | 262 | 272 | 275 | 278 | 281 | 291 | 294 | 297 | 300 | 303 | 306 | 309 | 312 | 313 | 314 | 315 | 316 | 317 | 322 | 325 | 326 | 327 | 332 | 333 | 338 | 339 | 340 | 341 | 342 | 343 | -------------------------------------------------------------------------------- /vc/test_tcp.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 28 | 31 | 34 | 37 | 40 | 43 | 53 | 56 | 59 | 62 | 70 | 73 | 76 | 79 | 82 | 85 | 88 | 91 | 92 | 100 | 103 | 106 | 109 | 112 | 115 | 125 | 128 | 131 | 134 | 144 | 147 | 150 | 153 | 156 | 159 | 162 | 165 | 166 | 173 | 176 | 179 | 182 | 185 | 189 | 199 | 202 | 205 | 208 | 216 | 219 | 222 | 225 | 228 | 231 | 234 | 237 | 238 | 246 | 249 | 252 | 255 | 258 | 262 | 272 | 275 | 278 | 281 | 291 | 294 | 297 | 300 | 303 | 306 | 309 | 312 | 313 | 314 | 315 | 316 | 317 | 322 | 325 | 326 | 327 | 332 | 333 | 338 | 339 | 340 | 341 | 342 | 343 | -------------------------------------------------------------------------------- /vc/test_tcp2.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 28 | 31 | 34 | 37 | 40 | 43 | 53 | 56 | 59 | 62 | 70 | 73 | 76 | 79 | 82 | 85 | 88 | 91 | 92 | 100 | 103 | 106 | 109 | 112 | 115 | 125 | 128 | 131 | 134 | 144 | 147 | 150 | 153 | 156 | 159 | 162 | 165 | 166 | 173 | 176 | 179 | 182 | 185 | 189 | 199 | 202 | 205 | 208 | 216 | 219 | 222 | 225 | 228 | 231 | 234 | 237 | 238 | 246 | 249 | 252 | 255 | 258 | 262 | 272 | 275 | 278 | 281 | 291 | 294 | 297 | 300 | 303 | 306 | 309 | 312 | 313 | 314 | 315 | 316 | 317 | 322 | 325 | 326 | 327 | 332 | 333 | 338 | 339 | 340 | 341 | 342 | 343 | -------------------------------------------------------------------------------- /vc/test_tcp3.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 28 | 31 | 34 | 37 | 40 | 43 | 53 | 56 | 59 | 62 | 70 | 73 | 76 | 79 | 82 | 85 | 88 | 91 | 92 | 100 | 103 | 106 | 109 | 112 | 115 | 125 | 128 | 131 | 134 | 144 | 147 | 150 | 153 | 156 | 159 | 162 | 165 | 166 | 173 | 176 | 179 | 182 | 185 | 189 | 199 | 202 | 205 | 208 | 216 | 219 | 222 | 225 | 228 | 231 | 234 | 237 | 238 | 246 | 249 | 252 | 255 | 258 | 262 | 272 | 275 | 278 | 281 | 291 | 294 | 297 | 300 | 303 | 306 | 309 | 312 | 313 | 314 | 315 | 316 | 317 | 322 | 325 | 326 | 327 | 332 | 333 | 338 | 339 | 340 | 341 | 342 | 343 | -------------------------------------------------------------------------------- /vc/test_udp.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 28 | 31 | 34 | 37 | 40 | 43 | 53 | 56 | 59 | 62 | 70 | 73 | 76 | 79 | 82 | 85 | 88 | 91 | 92 | 100 | 103 | 106 | 109 | 112 | 115 | 125 | 128 | 131 | 134 | 144 | 147 | 150 | 153 | 156 | 159 | 162 | 165 | 166 | 173 | 176 | 179 | 182 | 185 | 189 | 199 | 202 | 205 | 208 | 216 | 219 | 222 | 225 | 228 | 231 | 234 | 237 | 238 | 246 | 249 | 252 | 255 | 258 | 262 | 272 | 275 | 278 | 281 | 291 | 294 | 297 | 300 | 303 | 306 | 309 | 312 | 313 | 314 | 315 | 316 | 317 | 322 | 325 | 326 | 327 | 332 | 333 | 338 | 339 | 340 | 341 | 342 | 343 | -------------------------------------------------------------------------------- /vc/test_udp2.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 28 | 31 | 34 | 37 | 40 | 43 | 53 | 56 | 59 | 62 | 70 | 73 | 76 | 79 | 82 | 85 | 88 | 91 | 92 | 100 | 103 | 106 | 109 | 112 | 115 | 125 | 128 | 131 | 134 | 144 | 147 | 150 | 153 | 156 | 159 | 162 | 165 | 166 | 173 | 176 | 179 | 182 | 185 | 189 | 199 | 202 | 205 | 208 | 216 | 219 | 222 | 225 | 228 | 231 | 234 | 237 | 238 | 246 | 249 | 252 | 255 | 258 | 262 | 272 | 275 | 278 | 281 | 291 | 294 | 297 | 300 | 303 | 306 | 309 | 312 | 313 | 314 | 315 | 316 | 317 | 322 | 325 | 326 | 327 | 332 | 333 | 338 | 339 | 340 | 341 | 342 | 343 | -------------------------------------------------------------------------------- /vc/test_udp3.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 17 | 18 | 19 | 20 | 21 | 28 | 31 | 34 | 37 | 40 | 43 | 53 | 56 | 59 | 62 | 70 | 73 | 76 | 79 | 82 | 85 | 88 | 91 | 92 | 100 | 103 | 106 | 109 | 112 | 115 | 125 | 128 | 131 | 134 | 144 | 147 | 150 | 153 | 156 | 159 | 162 | 165 | 166 | 173 | 176 | 179 | 182 | 185 | 189 | 199 | 202 | 205 | 208 | 216 | 219 | 222 | 225 | 228 | 231 | 234 | 237 | 238 | 246 | 249 | 252 | 255 | 258 | 262 | 272 | 275 | 278 | 281 | 291 | 294 | 297 | 300 | 303 | 306 | 309 | 312 | 313 | 314 | 315 | 316 | 317 | 322 | 325 | 326 | 327 | 332 | 333 | 338 | 339 | 340 | 341 | 342 | 343 | -------------------------------------------------------------------------------- /vc/test_x64.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | cd %~dp0 4 | 5 | cd x64\Release 6 | 7 | echo test primitive 8 | (test_primitive && echo Succeed) || echo Failed 9 | echo test sleep 10 | (test_sleep > nul && echo Succeed) || echo Failed 11 | echo test udp [3] 12 | (test_udp > nul && echo Succeed) || echo Failed 13 | (test_udp2 > nul && echo Succeed) || echo Failed 14 | (test_udp3 > nul && echo Succeed) || echo Failed 15 | echo test tcp [3] 16 | (test_tcp > nul && echo Succeed) || echo Failed 17 | (test_tcp2 > nul && echo Succeed) || echo Failed 18 | (test_tcp3 > nul && echo Succeed) || echo Failed 19 | echo test tcp timing 20 | (unexpected_tcp_timing > nul && echo Succeed) || echo Failed 21 | echo test getaddrinfo 22 | (test_getaddrinfo > nul && echo Succeed) || echo Failed 23 | echo benchmark sleep 24 | (benchmark_sleep > nul && echo Succeed) || echo Failed 25 | echo benchmark udp 26 | (benchmark_udp2 > nul && echo Succeed) || echo Failed 27 | echo benchmark tcp 28 | (benchmark_tcp > nul && echo Succeed) || echo Failed 29 | 30 | pause 31 | -------------------------------------------------------------------------------- /vcbuild.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | cd %~dp0 4 | 5 | set CCF_UV_VERSION=0.10.27 6 | 7 | set CCF_PLATFORM=x86 8 | if "%PROCESSOR_ARCHITECTURE%"=="AMD64" set CCF_PLATFORM=x64 9 | if "%1"=="x86" set CCF_PLATFORM=x86 10 | if "%1"=="x64" set CCF_PLATFORM=x64 11 | 12 | set CCF_MS_PLATFORM=WIN32 13 | if "%CCF_PLATFORM%"=="x64" set CCF_MS_PLATFORM=WIN64 14 | set CCF_LIB_PATH= 15 | if "%CCF_PLATFORM%"=="x64" set CCF_LIB_PATH=x64\ 16 | 17 | if exist lib\Release\libuv.lib goto check_msvc 18 | 19 | echo Compiling libuv ... 20 | cd deps 21 | unzip gyp.zip > nul 22 | unzip libuv-%CCF_UV_VERSION%.zip > nul 23 | cd libuv-%CCF_UV_VERSION%\ 24 | md build 25 | md build\gyp 26 | xcopy /E ..\gyp build\gyp > nul 27 | call vcbuild debug %CCF_PLATFORM% 28 | call vcbuild release %CCF_PLATFORM% 29 | 30 | cd %~dp0 31 | md src\uv 32 | xcopy /E deps\libuv-%CCF_UV_VERSION%\include src\uv > nul 33 | md lib\Debug 34 | md lib\Release 35 | xcopy deps\libuv-%CCF_UV_VERSION%\Debug\lib\libuv.lib lib\Debug\ > nul 36 | xcopy deps\libuv-%CCF_UV_VERSION%\Release\lib\libuv.lib lib\Release\ > nul 37 | 38 | :check_msvc 39 | @rem Look for Visual Studio 2013 40 | if not defined VS120COMNTOOLS goto vc-set-2012 41 | if not exist "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2012 42 | call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" %CCF_PLATFORM% 43 | goto upgrade 44 | 45 | :vc-set-2012 46 | @rem Look for Visual Studio 2012 47 | if not defined VS110COMNTOOLS goto vc-set-2010 48 | if not exist "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2010 49 | call "%VS110COMNTOOLS%\..\..\vc\vcvarsall.bat" %CCF_PLATFORM% 50 | goto upgrade 51 | 52 | :vc-set-2010 53 | @rem Look for Visual Studio 2010 54 | if not defined VS100COMNTOOLS goto vc-set-2008 55 | if not exist "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2008 56 | call "%VS100COMNTOOLS%\..\..\vc\vcvarsall.bat" %CCF_PLATFORM% 57 | goto upgrade 58 | 59 | :vc-set-2008 60 | @rem Look for Visual Studio 2008 61 | if not defined VS90COMNTOOLS goto vc-set-notfound 62 | if not exist "%VS90COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-notfound 63 | call "%VS90COMNTOOLS%\..\..\vc\vcvarsall.bat" %CCF_PLATFORM% 64 | goto msbuild 65 | 66 | :vc-set-notfound 67 | echo Error: Visual Studio not found 68 | goto exit 69 | 70 | :upgrade 71 | echo Upgrading for Visual Studio ... 72 | devenv /upgrade vc\cocoflow.sln 73 | 74 | :msbuild 75 | echo Compiling libccf ... 76 | msbuild vc\cocoflow.sln /t:libccf /p:Configuration=Debug /p:Platform="%CCF_MS_PLATFORM%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo 77 | msbuild vc\cocoflow.sln /t:libccf /p:Configuration=Release /p:Platform="%CCF_MS_PLATFORM%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo 78 | xcopy /Y vc\%CCF_LIB_PATH%Debug\libccf.lib lib\Debug\ > nul 79 | xcopy /Y vc\%CCF_LIB_PATH%Release\libccf.lib lib\Release\ > nul 80 | 81 | echo Compiling demo ... 82 | msbuild vc\cocoflow.sln /t:demo_all_sort,demo_any_sort,demo_http_server /p:Configuration=Debug /p:Platform="%CCF_MS_PLATFORM%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo 83 | msbuild vc\cocoflow.sln /t:demo_all_sort,demo_any_sort,demo_http_server /p:Configuration=Release /p:Platform="%CCF_MS_PLATFORM%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo 84 | 85 | echo Compiling test ... 86 | msbuild vc\cocoflow.sln /t:test_primitive,test_sleep,test_tcp,test_tcp2,test_tcp3,test_udp,test_udp2,test_udp3,unexpected_tcp_timing,test_getaddrinfo /p:Configuration=Debug /p:Platform="%CCF_MS_PLATFORM%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo 87 | msbuild vc\cocoflow.sln /t:test_primitive,test_sleep,test_tcp,test_tcp2,test_tcp3,test_udp,test_udp2,test_udp3,unexpected_tcp_timing,test_getaddrinfo /p:Configuration=Release /p:Platform="%CCF_MS_PLATFORM%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo 88 | msbuild vc\cocoflow.sln /t:benchmark_sleep,benchmark_tcp,benchmark_udp,benchmark_udp2 /p:Configuration=Debug /p:Platform="%CCF_MS_PLATFORM%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo 89 | msbuild vc\cocoflow.sln /t:benchmark_sleep,benchmark_tcp,benchmark_udp,benchmark_udp2 /p:Configuration=Release /p:Platform="%CCF_MS_PLATFORM%" /clp:NoSummary;NoItemAndPropertyList;Verbosity=minimal /nologo 90 | 91 | :exit 92 | pause 93 | --------------------------------------------------------------------------------