├── .gitmodules
├── CMakeLists.txt
├── JniAtomiThreadPool_Linux_Mac
├── build_linux.sh
└── build_mac.sh
├── JniAtomiThreadPool_VS
├── JniAtomiThreadPool_VS.sln
├── JniAtomiThreadPool_VS.vcxproj
└── JniAtomiThreadPool_VS.vcxproj.filters
├── LICENSE
├── README.md
├── at_thpool.c
├── at_thpool.h
├── cmake_uninstall.cmake.in
├── java_source
├── pom.xml
└── src
│ ├── main
│ ├── java
│ │ └── com
│ │ │ └── github
│ │ │ └── taymindis
│ │ │ ├── AtomicThreadPool.java
│ │ │ ├── AtomicThreadPoolTask.java
│ │ │ └── NativeUtils.java
│ └── resources
│ │ ├── VS32.dll
│ │ ├── VS32_full.dll
│ │ ├── VS64.dll
│ │ ├── VS64_full.dll
│ │ └── libatpool_jni.so
│ └── test
│ └── java
│ └── com
│ └── github
│ └── taymindis
│ └── test
│ ├── MyTask.java
│ └── Test1.java
├── jni-cross-platform
├── AtomicThreadPool.c
└── AtomicThreadPool.h
└── threadpool_example.c
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "lfqueue"]
2 | path = lfqueue
3 | url = https://github.com/Taymindis/lfqueue.git
4 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 2.8)
2 | project(athpool)
3 |
4 | set(PROJNAME athpool)
5 |
6 | IF (WIN32 OR MSVC OR MSYS OR MINGW OR APPLE)
7 | message( FATAL_ERROR "for windows build, please open with visual studio project")
8 | endif()
9 |
10 | MESSAGE(STATUS "Unix Build ... ")
11 |
12 | IF (NOT DEFINED CMAKE_INSTALL_INCLUDEDIR)
13 | SET(CMAKE_INSTALL_INCLUDEDIR /usr/local/include)
14 | ENDIF(NOT DEFINED CMAKE_INSTALL_INCLUDEDIR)
15 |
16 | include_directories(/usr/local/include /usr/include lfqueue)
17 |
18 | file(GLOB_RECURSE sources at_thpool.h at_thpool.c lfqueue/lfqueue.h lfqueue/lfqueue.c)
19 | file(GLOB_RECURSE example_test ${sources} threadpool_example.c)
20 |
21 | add_executable(example_threadpool ${example_test})
22 | target_link_libraries(example_threadpool PUBLIC pthread)
23 |
24 |
25 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -Wall -Wstrict-prototypes -Wmissing-prototypes")
26 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual")
27 | SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wsign-compare -pedantic")
28 |
29 | ###############################################################################
30 | ## packaging ##################################################################
31 | ###############################################################################
32 | add_library(${PROJNAME}.static STATIC ${sources})
33 | target_link_libraries(${PROJNAME}.static pthread)
34 | set_target_properties(${PROJNAME}.static PROPERTIES OUTPUT_NAME ${PROJNAME})
35 | add_library(${PROJNAME} SHARED ${sources})
36 | target_link_libraries(${PROJNAME} pthread)
37 |
38 |
39 | # link_directories(/usr/local/lib /usr/lib)
40 |
41 | ## For .a library
42 | install(TARGETS ${PROJNAME}.static EXPORT ${PROJNAME}
43 | ARCHIVE DESTINATION lib${LIB_SUFFIX}
44 | LIBRARY DESTINATION lib${LIB_SUFFIX}
45 | # RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
46 | )
47 |
48 | ## For .so library
49 | install(TARGETS ${PROJNAME} EXPORT ${PROJNAME}
50 | ARCHIVE DESTINATION lib${LIB_SUFFIX}
51 | LIBRARY DESTINATION lib${LIB_SUFFIX}
52 | # RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
53 | )
54 | install(FILES at_thpool.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
55 |
56 | install(CODE "execute_process(COMMAND ldconfig)")
57 |
58 |
59 | configure_file(
60 | "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
61 | "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
62 | IMMEDIATE @ONLY)
63 |
64 | add_custom_target(uninstall
65 | COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
66 |
67 |
68 | set(CPACK_PACKAGE_NAME "at_thpool")
69 | set(CPACK_PACKAGE_VERSION "1.0.0")
70 |
71 | # we don't want to split our program up into several things
72 | set(CPACK_MONOLITHIC_INSTALL 1)
73 |
74 | # This must be last
75 | include(CPack)
76 |
--------------------------------------------------------------------------------
/JniAtomiThreadPool_Linux_Mac/build_linux.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | gcc -shared -o libatpool_jni.so -fPIC -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -I$JAVAHOME/include/darwin -I/usr/local/include -I/usr/include -I../ -I../lfqueue -I../jni-cross-platform ../lfqueue/lfqueue.c ../at_thpool.c ../jni-cross-platform/AtomicThreadPool.c -pthread
4 |
--------------------------------------------------------------------------------
/JniAtomiThreadPool_Linux_Mac/build_mac.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 |
4 | clang -dynamiclib -O3 -I$JAVA_HOME/include -I$JAVA_HOME/include/linux -I$JAVAHOME/include/darwin -I/usr/local/include -I/usr/include -I../ -I../lfqueue -I../jni-cross-platform ../lfqueue/lfqueue.c ../at_thpool.c ../jni-cross-platform/AtomicThreadPool.c -o libatpool_jni.dylib
5 |
--------------------------------------------------------------------------------
/JniAtomiThreadPool_VS/JniAtomiThreadPool_VS.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27703.2042
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JniAtomiThreadPool_VS", "JniAtomiThreadPool_VS.vcxproj", "{50C8DCEE-CAFF-42E0-9B3B-9A8E76FF7D9D}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x64 = Debug|x64
11 | Debug|x86 = Debug|x86
12 | FullPackMT|x64 = FullPackMT|x64
13 | FullPackMT|x86 = FullPackMT|x86
14 | Release|x64 = Release|x64
15 | Release|x86 = Release|x86
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {50C8DCEE-CAFF-42E0-9B3B-9A8E76FF7D9D}.Debug|x64.ActiveCfg = Debug|x64
19 | {50C8DCEE-CAFF-42E0-9B3B-9A8E76FF7D9D}.Debug|x64.Build.0 = Debug|x64
20 | {50C8DCEE-CAFF-42E0-9B3B-9A8E76FF7D9D}.Debug|x86.ActiveCfg = Debug|Win32
21 | {50C8DCEE-CAFF-42E0-9B3B-9A8E76FF7D9D}.Debug|x86.Build.0 = Debug|Win32
22 | {50C8DCEE-CAFF-42E0-9B3B-9A8E76FF7D9D}.FullPackMT|x64.ActiveCfg = FullPackMT|x64
23 | {50C8DCEE-CAFF-42E0-9B3B-9A8E76FF7D9D}.FullPackMT|x64.Build.0 = FullPackMT|x64
24 | {50C8DCEE-CAFF-42E0-9B3B-9A8E76FF7D9D}.FullPackMT|x86.ActiveCfg = FullPackMT|Win32
25 | {50C8DCEE-CAFF-42E0-9B3B-9A8E76FF7D9D}.FullPackMT|x86.Build.0 = FullPackMT|Win32
26 | {50C8DCEE-CAFF-42E0-9B3B-9A8E76FF7D9D}.Release|x64.ActiveCfg = Release|x64
27 | {50C8DCEE-CAFF-42E0-9B3B-9A8E76FF7D9D}.Release|x64.Build.0 = Release|x64
28 | {50C8DCEE-CAFF-42E0-9B3B-9A8E76FF7D9D}.Release|x86.ActiveCfg = Release|Win32
29 | {50C8DCEE-CAFF-42E0-9B3B-9A8E76FF7D9D}.Release|x86.Build.0 = Release|Win32
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {F32C1D7F-2436-4472-BDED-33D559FF7B26}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/JniAtomiThreadPool_VS/JniAtomiThreadPool_VS.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | FullPackMT
10 | Win32
11 |
12 |
13 | FullPackMT
14 | x64
15 |
16 |
17 | Release
18 | Win32
19 |
20 |
21 | Debug
22 | x64
23 |
24 |
25 | Release
26 | x64
27 |
28 |
29 |
30 | 15.0
31 | {50C8DCEE-CAFF-42E0-9B3B-9A8E76FF7D9D}
32 | JniAtomiThreadPoolVS
33 | 8.1
34 |
35 |
36 |
37 | DynamicLibrary
38 | true
39 | v140
40 | MultiByte
41 |
42 |
43 | DynamicLibrary
44 | false
45 | v140
46 | true
47 | MultiByte
48 |
49 |
50 | DynamicLibrary
51 | false
52 | v140
53 | true
54 | MultiByte
55 |
56 |
57 | DynamicLibrary
58 | true
59 | v140
60 | MultiByte
61 |
62 |
63 | DynamicLibrary
64 | false
65 | v140
66 | true
67 | MultiByte
68 |
69 |
70 | DynamicLibrary
71 | false
72 | v140
73 | true
74 | MultiByte
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 | Level3
104 | Disabled
105 | true
106 | C:\msys64\home\woonsh\git-project\atomic_threadpool;C:\msys64\home\woonsh\git-project\atomic_threadpool\lfqueue;C:\msys64\home\woonsh\git-project\atomic_threadpool\jni-cross-platform;C:\Program Files\Java\jdk1.7.0_10\include;C:\Program Files\Java\jdk1.7.0_10\include\win32;%(AdditionalIncludeDirectories)
107 | MultiThreaded
108 |
109 |
110 |
111 |
112 | Level3
113 | Disabled
114 | true
115 | C:\msys64\home\woonsh\git-project\atomic_threadpool;C:\msys64\home\woonsh\git-project\atomic_threadpool\lfqueue;C:\msys64\home\woonsh\git-project\atomic_threadpool\jni-cross-platform;C:\Program Files\Java\jdk1.7.0_10\include;C:\Program Files\Java\jdk1.7.0_10\include\win32;%(AdditionalIncludeDirectories)
116 | MultiThreaded
117 |
118 |
119 |
120 |
121 | Level3
122 | MaxSpeed
123 | true
124 | true
125 | true
126 | C:\msys64\home\woonsh\git-project\atomic_threadpool;C:\msys64\home\woonsh\git-project\atomic_threadpool\lfqueue;C:\msys64\home\woonsh\git-project\atomic_threadpool\jni-cross-platform;C:\Program Files\Java\jdk1.7.0_10\include;C:\Program Files\Java\jdk1.7.0_10\include\win32;%(AdditionalIncludeDirectories)
127 | MultiThreadedDLL
128 |
129 |
130 | true
131 | true
132 |
133 |
134 |
135 |
136 | Level3
137 | MaxSpeed
138 | true
139 | true
140 | true
141 | C:\msys64\home\woonsh\git-project\atomic_threadpool;C:\msys64\home\woonsh\git-project\atomic_threadpool\lfqueue;C:\msys64\home\woonsh\git-project\atomic_threadpool\jni-cross-platform;C:\Program Files\Java\jdk1.7.0_10\include;C:\Program Files\Java\jdk1.7.0_10\include\win32;%(AdditionalIncludeDirectories)
142 | MultiThreaded
143 |
144 |
145 | true
146 | true
147 |
148 |
149 |
150 |
151 | Level3
152 | MaxSpeed
153 | true
154 | true
155 | true
156 | C:\msys64\home\woonsh\git-project\atomic_threadpool;C:\msys64\home\woonsh\git-project\atomic_threadpool\lfqueue;C:\msys64\home\woonsh\git-project\atomic_threadpool\jni-cross-platform;C:\Program Files\Java\jdk1.7.0_10\include;C:\Program Files\Java\jdk1.7.0_10\include\win32;%(AdditionalIncludeDirectories)
157 | MultiThreadedDLL
158 |
159 |
160 | true
161 | true
162 |
163 |
164 |
165 |
166 | Level3
167 | MaxSpeed
168 | true
169 | true
170 | true
171 | C:\msys64\home\woonsh\git-project\atomic_threadpool;C:\msys64\home\woonsh\git-project\atomic_threadpool\lfqueue;C:\msys64\home\woonsh\git-project\atomic_threadpool\jni-cross-platform;C:\Program Files\Java\jdk1.7.0_10\include;C:\Program Files\Java\jdk1.7.0_10\include\win32;%(AdditionalIncludeDirectories)
172 | MultiThreaded
173 |
174 |
175 | true
176 | true
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
--------------------------------------------------------------------------------
/JniAtomiThreadPool_VS/JniAtomiThreadPool_VS.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF}
6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx
7 |
8 |
9 | {93995380-89BD-4b04-88EB-625FBE52EBFB}
10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd
11 |
12 |
13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
15 |
16 |
17 |
18 |
19 | Source Files
20 |
21 |
22 | Source Files
23 |
24 |
25 | Source Files
26 |
27 |
28 |
29 |
30 | Header Files
31 |
32 |
33 | Header Files
34 |
35 |
36 | Header Files
37 |
38 |
39 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 2-Clause License
2 |
3 | Copyright (c) 2018, Taymindis Woon
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
20 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
23 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # atomic_threadpool
2 | it is c/c++ library, it's a smallest library that provides a lock-free thread pool sharing on multithreading, it design for scalability
3 |
4 |
5 | ## For Linux OS build
6 |
7 | ## Installation
8 |
9 | ```bash
10 | mkdir build
11 |
12 | cd build
13 |
14 | cmake ..
15 |
16 | make
17 |
18 | sudo make install
19 |
20 | ```
21 |
22 |
23 |
24 | ## Uninstallation
25 |
26 | ```bash
27 | cd build
28 |
29 | sudo make uninstall
30 |
31 | ```
32 |
33 |
34 | ## Example to run
35 | ```c
36 |
37 | #include
38 | #include
39 | #include "at_thpool.h"
40 |
41 |
42 | #define TASK_SIZE 200
43 |
44 | void t1(void *arg);
45 | void t2(void *arg);
46 | void t3(void *arg);
47 | void t4(void *arg);
48 |
49 | void t1(void *arg) {
50 | printf("t1 is running on thread #%u \n", (int)pthread_self());
51 | }
52 |
53 | void t2(void *arg) {
54 | printf("t2 is running on thread #%u\n", (int)pthread_self());
55 | }
56 |
57 | void t3(void *arg) {
58 | printf("t3 is running on thread #%u\n", (int)pthread_self());
59 | }
60 |
61 | void t4(void *arg) {
62 | printf("t4 is running on thread #%u\n", (int)pthread_self());
63 | }
64 |
65 | int main(void) {
66 | int nthreads = 8;//sysconf(_SC_NPROCESSORS_ONLN); // Linux
67 |
68 | printf("Share thread pool with %d threads with at lease totalthroughput * nthreads task size\n", nthreads);
69 | at_thpool_t *thpool = at_thpool_create(nthreads);
70 |
71 | printf("assigned %d tasks between %d threads\n", TASK_SIZE, nthreads);
72 | int i;
73 | for (i = 0; i < TASK_SIZE; i++) {
74 | at_thpool_newtask(thpool, t1, NULL);
75 | at_thpool_newtask(thpool, t2, NULL);
76 | at_thpool_newtask(thpool, t3, NULL);
77 | at_thpool_newtask(thpool, t4, NULL);
78 | }
79 |
80 | #if defined _WIN32 || _WIN64
81 | Sleep(1000);
82 | #else
83 | usleep(1000 * 1000);
84 | #endif
85 |
86 | puts("shutdown thread pool");
87 | at_thpool_gracefully_shutdown(thpool);
88 |
89 | return 0;
90 | }
91 |
92 | ```
93 |
94 |
95 | ### How to wait for task to finish on main thread
96 |
97 | AtomicThreadPool design for lock free, it does not wait for anyone, to wait for specified task to finished, client should pass the value to indicate it has done.
98 |
99 | For Example for wait task:
100 |
101 | ```c
102 |
103 | #include
104 | #include
105 | #include "at_thpool.h"
106 |
107 | typedef struct myagent_s {
108 | int has_task_done;
109 | void *my_value;
110 | } my_agent;
111 |
112 | void t1(void *arg);
113 |
114 | void t1(void *arg) {
115 | my_agent *agent = (my_agent*) arg;
116 |
117 | printf("t1 is running on thread #%u \n", (int)pthread_self());
118 |
119 | /** Doing heavy task **/
120 |
121 | agent->has_task_done = 1;
122 |
123 | }
124 |
125 | int main(void) {
126 | int nthreads = 8;//sysconf(_SC_NPROCESSORS_ONLN); // Linux
127 |
128 | printf("Share thread pool with %d threads with at lease totalthroughput * nthreads task size\n", nthreads);
129 | at_thpool_t *thpool = at_thpool_create(nthreads);
130 |
131 | int i;
132 | my_agent agent;
133 | agent.has_task_done = 0
134 |
135 | at_thpool_newtask(thpool, t1, &agent);
136 | while (!agent.has_task_done) {
137 | #if defined _WIN32 || _WIN64
138 | Sleep(1);
139 | #else
140 | usleep(1000);
141 | #endif
142 | }
143 |
144 | puts("shutdown thread pool");
145 | at_thpool_gracefully_shutdown(thpool);
146 |
147 | return 0;
148 | }
149 |
150 |
151 | ```
152 |
153 |
154 | ## For manual build
155 | gcc -std=c11 -I./ -Ilfqueue/ at_thpool.c lfqueue/lfqueue.c threadpool_example.c -pthread
156 |
157 |
158 | ## for Windows os build
159 |
160 | ### Recommend to use VS2017 to build
161 |
162 | #### include the sources file at_thpool.c at_thpool.h lfqueue.c lfqueue.h into VS2017 project solution.
163 |
164 | Alternatively,
165 |
166 | #### Download the Dev-C++ IDE - https://sourceforge.net/projects/orwelldevcpp/
167 |
168 |
169 |
170 | #### You can use any IDE/build tools as you wish, just include the source files to your project
171 |
172 |
173 |
174 |
175 |
--------------------------------------------------------------------------------
/at_thpool.c:
--------------------------------------------------------------------------------
1 | /*
2 | * BSD 2-Clause License
3 | *
4 | * Copyright (c) 2018, Taymindis Woon
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without
8 | * modification, are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice, this
11 | * list of conditions and the following disclaimer.
12 | *
13 | * * Redistributions in binary form must reproduce the above copyright notice,
14 | * this list of conditions and the following disclaimer in the documentation
15 | * and/or other materials provided with the distribution.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 | #include
29 | #include
30 | #include
31 |
32 | #if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__
33 | #include
34 | #include
35 | #elif defined _WIN32 || _WIN64
36 | #include
37 | #include
38 | #endif
39 |
40 | #include "lfqueue.h"
41 | #include "at_thpool.h"
42 |
43 | /**
44 | * Over max thread will affect the system scalability, it might not scale well
45 | */
46 | #define MAX_THREADS 64
47 | #define MAX_LFQUEUE 65536
48 |
49 | #define AT_THPOOL_ERROR perror
50 | #define DEF_SPIN_LOCK_CYCLE 2048
51 | #define AT_THPOOL_MALLOC malloc
52 | #define AT_THPOOL_FREE free
53 |
54 | #if defined _WIN32
55 | #define AT_THPOOL_INC(v) InterlockedExchangeAddNoFence(v, 1)
56 | #define AT_THPOOL_DEC(v) InterlockedExchangeAddNoFence(v, -1)
57 | #define AT_THPOOL_SHEDYIELD SwitchToThread
58 | #elif defined _WIN64
59 | #define AT_THPOOL_INC(v) InterlockedExchangeAddNoFence64(v, 1)
60 | #define AT_THPOOL_DEC(v) InterlockedExchangeAddNoFence64(v, -1)
61 | #define AT_THPOOL_SHEDYIELD SwitchToThread
62 | #else
63 | #define AT_THPOOL_INC(v) __sync_fetch_and_add(v, 1)
64 | #define AT_THPOOL_DEC(v) __sync_fetch_and_add(v, -1)
65 | #define AT_THPOOL_SHEDYIELD sched_yield
66 | #endif
67 |
68 | typedef struct {
69 | void (*do_work)(void *);
70 | void *args;
71 | } at_thtask_t;
72 |
73 | struct at_thpool_s {
74 | #if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__
75 | pthread_t *threads;
76 | #elif defined _WIN32 || _WIN64
77 | HANDLE *threads;
78 | #endif
79 | lfqueue_t taskqueue;
80 | size_t nrunning;
81 | int is_running;
82 | };
83 |
84 | #if defined _WIN32 || defined _WIN64
85 | unsigned __stdcall at_thpool_worker(void *);
86 | #else
87 | void* at_thpool_worker(void *);
88 | #endif
89 |
90 | at_thpool_t *
91 | at_thpool_create(size_t nthreads) {
92 | size_t i;
93 | if (nthreads > MAX_THREADS) {
94 | fprintf(stderr, "The nthreads is > %d, over max thread will affect the system scalability, it might not scale well\n", MAX_THREADS);
95 | }
96 |
97 | at_thpool_t *tp;
98 | tp = (at_thpool_t*) AT_THPOOL_MALLOC(sizeof(at_thpool_t));
99 | if (tp == NULL) {
100 | AT_THPOOL_ERROR("malloc");
101 | return NULL;
102 | }
103 |
104 | #if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__
105 | tp->threads = (pthread_t *)AT_THPOOL_MALLOC(sizeof(pthread_t) * nthreads);
106 | #elif defined _WIN32 || _WIN64
107 | tp->threads = (HANDLE)AT_THPOOL_MALLOC(sizeof(HANDLE) * nthreads);
108 | #endif
109 |
110 | tp->nrunning = 0;
111 | if (tp->threads == NULL) {
112 | AT_THPOOL_ERROR("malloc");
113 | AT_THPOOL_FREE(tp);
114 | return NULL;
115 | }
116 |
117 | if (lfqueue_init(&tp->taskqueue) < 0) {
118 | AT_THPOOL_ERROR("malloc");
119 | AT_THPOOL_FREE(tp->threads);
120 | AT_THPOOL_FREE(tp);
121 | return NULL;
122 | }
123 |
124 | tp->is_running = 1;
125 |
126 | #if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__
127 | for (i = 0; i < nthreads; i++) {
128 | if (pthread_create(&(tp->threads[i]), NULL, at_thpool_worker, (void*)tp)) {
129 | if (i != 0) {
130 | fprintf(stderr, "maximum thread has reached %zu \n", i );
131 | break;
132 | } else {
133 | AT_THPOOL_ERROR("Failed to establish thread pool");
134 | at_thpool_immediate_shutdown(tp);
135 | }
136 | }
137 | pthread_detach(tp->threads[i]);
138 | }
139 | #elif defined _WIN32 || _WIN64
140 | for (i = 0; i < nthreads; i++) {
141 | unsigned udpthreadid;
142 | tp->threads[i] = (HANDLE)_beginthreadex(NULL, 0, at_thpool_worker, (void *)tp, 0, &udpthreadid);
143 | if (tp->threads[i] == 0) {
144 | if (i != 0) {
145 | fprintf(stderr, "maximum thread has reached %lld \n", i);
146 | }
147 | else {
148 | AT_THPOOL_ERROR("Failed to establish thread pool");
149 | at_thpool_immediate_shutdown(tp);
150 | }
151 | }
152 | CloseHandle(tp->threads[i]);
153 | }
154 | #endif
155 | return tp;
156 | }
157 |
158 | #if defined _WIN32 || defined _WIN64
159 | unsigned __stdcall at_thpool_worker(void *_tp) {
160 | #else
161 | void* at_thpool_worker(void *_tp) {
162 | #endif
163 | at_thpool_t *tp = (at_thpool_t*)_tp;
164 | AT_THPOOL_INC(&tp->nrunning);
165 |
166 | at_thtask_t *task;
167 | void *_task;
168 | lfqueue_t *tq = &tp->taskqueue;
169 |
170 | TASK_PENDING:
171 | while (tp->is_running) {
172 | if ( (_task = lfqueue_deq(tq)) ) {
173 | goto HANDLE_TASK;
174 | }
175 | lfqueue_sleep(1);
176 | }
177 |
178 | AT_THPOOL_DEC(&tp->nrunning);
179 | #if defined _WIN32 || defined _WIN64
180 | return 0;
181 | #else
182 | return NULL;
183 | #endif
184 | HANDLE_TASK:
185 | task = (at_thtask_t*) _task;
186 | task->do_work(task->args);
187 | AT_THPOOL_FREE(task);
188 | goto TASK_PENDING;
189 | }
190 |
191 | int
192 | at_thpool_newtask(at_thpool_t *tp, void (*task_pt)(void *), void *arg) {
193 | at_thtask_t *task = AT_THPOOL_MALLOC(sizeof(at_thtask_t));
194 |
195 | if (task == NULL) {
196 | AT_THPOOL_ERROR("malloc");
197 | return errno;
198 | }
199 |
200 | task->do_work = task_pt;
201 | task->args = arg;
202 |
203 | if (lfqueue_enq(&tp->taskqueue, task) == -1) {
204 | fprintf(stderr, "Task unable to assigned to pool, it might be full\n");
205 | AT_THPOOL_FREE(task);
206 | return -1;
207 | }
208 | return 0;
209 | }
210 |
211 | void
212 | at_thpool_gracefully_shutdown(at_thpool_t *tp) {
213 | tp->is_running = 0;
214 | int i, ncycle = DEF_SPIN_LOCK_CYCLE;
215 | for (;;) {
216 | for (i = 0; i < ncycle; i++) {
217 | if (tp->nrunning == 0) {
218 | goto SHUTDOWN;
219 | }
220 | }
221 | AT_THPOOL_SHEDYIELD();
222 | }
223 | SHUTDOWN:
224 | lfqueue_destroy(&tp->taskqueue);
225 | lfqueue_sleep(100);
226 | AT_THPOOL_FREE(tp->threads);
227 | AT_THPOOL_FREE(tp);
228 |
229 | }
230 |
231 | void
232 | at_thpool_immediate_shutdown(at_thpool_t *tp) {
233 | tp->is_running = 0;
234 | AT_THPOOL_FREE(tp->threads);
235 | lfqueue_destroy(&tp->taskqueue);
236 | AT_THPOOL_FREE(tp);
237 | }
238 |
--------------------------------------------------------------------------------
/at_thpool.h:
--------------------------------------------------------------------------------
1 | /*
2 | * BSD 2-Clause License
3 | *
4 | * Copyright (c) 2018, Taymindis Woon
5 | * All rights reserved.
6 | *
7 | * Redistribution and use in source and binary forms, with or without
8 | * modification, are permitted provided that the following conditions are met:
9 | *
10 | * * Redistributions of source code must retain the above copyright notice, this
11 | * list of conditions and the following disclaimer.
12 | *
13 | * * Redistributions in binary form must reproduce the above copyright notice,
14 | * this list of conditions and the following disclaimer in the documentation
15 | * and/or other materials provided with the distribution.
16 | *
17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
24 | * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 | */
28 |
29 | #ifndef _AT_THREADPOOL_H_
30 | #define _AT_THREADPOOL_H_
31 |
32 | #ifdef __cplusplus
33 | extern "C" {
34 | #endif
35 |
36 |
37 | typedef struct at_thpool_s at_thpool_t;
38 |
39 | at_thpool_t *at_thpool_create(size_t nthreads);
40 |
41 | int at_thpool_newtask(at_thpool_t *pool, void (*task_pt)(void *),void *arg);
42 |
43 | void at_thpool_gracefully_shutdown(at_thpool_t *tp);
44 | void at_thpool_immediate_shutdown(at_thpool_t *tp);
45 |
46 | #ifdef __cplusplus
47 | }
48 | #endif
49 |
50 | #endif /* _AT_THREADPOOL_H_ */
51 |
--------------------------------------------------------------------------------
/cmake_uninstall.cmake.in:
--------------------------------------------------------------------------------
1 | if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
2 | message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
3 | endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
4 |
5 | file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
6 | string(REGEX REPLACE "\n" ";" files "${files}")
7 | foreach(file ${files})
8 | message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
9 | if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
10 | exec_program(
11 | "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
12 | OUTPUT_VARIABLE rm_out
13 | RETURN_VALUE rm_retval
14 | )
15 | if(NOT "${rm_retval}" STREQUAL 0)
16 | message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
17 | endif(NOT "${rm_retval}" STREQUAL 0)
18 | else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
19 | message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
20 | endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
21 | endforeach(file)
--------------------------------------------------------------------------------
/java_source/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.github.taymindis
8 | AtomicThreadPool
9 | ${current.version}
10 | jar
11 | AtomicThreadPool
12 | This is a library which depends on Native C Library https://github.com/Taymindis/atomic_threadpool
13 |
14 |
15 | 1.0-SNAPSHOT
16 |
17 |
18 |
19 | BSD 2-Clause License
20 | https://opensource.org/licenses/BSD-2-Clause
21 | repo
22 |
23 |
24 | https://github.com/Taymindis/atomic_threadpool
25 |
26 | https://github.com/Taymindis/atomic_threadpool.git
27 | scm:git:git://github.com/Taymindis/atomic_threadpool.git
28 | scm:git:git://github.com/Taymindis/atomic_threadpool.git
29 |
30 |
31 | GitHub
32 | https://github.com/Taymindis/atomic_threadpool/issues
33 |
34 |
35 |
36 |
37 | taymindis
38 | Taymindis Woon
39 | minikawoon2017@gmail.com
40 |
41 |
42 |
43 |
44 |
45 | ossrh
46 | https://oss.sonatype.org/content/repositories/snapshots
47 |
48 |
49 | ossrh
50 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
51 |
52 |
53 |
54 |
55 |
56 | junit
57 | junit
58 | 4.12
59 | test
60 |
61 |
62 |
63 |
64 |
65 |
66 | org.apache.maven.plugins
67 | maven-source-plugin
68 | 2.2.1
69 |
70 |
71 | attach-sources
72 |
73 | jar-no-fork
74 |
75 |
76 |
77 |
78 |
79 | org.apache.maven.plugins
80 | maven-javadoc-plugin
81 | 2.9.1
82 |
83 |
84 | attach-javadocs
85 |
86 | jar
87 |
88 |
89 |
90 |
91 |
92 | org.apache.maven.plugins
93 | maven-gpg-plugin
94 | 1.5
95 |
96 |
97 | sign-artifacts
98 | verify
99 |
100 | sign
101 |
102 |
103 |
104 |
105 |
106 | org.apache.maven.plugins
107 | maven-compiler-plugin
108 | 3.1
109 |
110 | 1.7
111 | 1.7
112 |
113 |
114 |
115 |
116 | org.apache.maven.plugins
117 | maven-gpg-plugin
118 | 1.5
119 |
120 |
121 | org.apache.maven.plugins
122 | maven-release-plugin
123 | 2.4.2
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/java_source/src/main/java/com/github/taymindis/AtomicThreadPool.java:
--------------------------------------------------------------------------------
1 | package com.github.taymindis;
2 |
3 | import java.io.IOException;
4 | import java.util.logging.Logger;
5 |
6 | /**
7 | * Created by woonsh on 10/9/2018.
8 | */
9 | public class AtomicThreadPool {
10 | private long threadpoolPtr = -1;
11 | private static String OS = System.getProperty("os.name").toLowerCase();
12 | private static final Logger logger = Logger.getLogger(AtomicThreadPool.class.getName());
13 |
14 | public AtomicThreadPool(int nthreads) {
15 | try {
16 | if (!init(nthreads)) {
17 | throw new Exception("Unable to initialize thread pool correctly");
18 | }
19 | }catch (Exception e) {
20 | e.printStackTrace();
21 | }
22 | }
23 |
24 | public native boolean newTask(AtomicThreadPoolTask o);
25 | public native boolean shutdown();
26 |
27 | public long getThreadpoolPtr() {
28 | return threadpoolPtr;
29 | }
30 |
31 | public void setThreadpoolPtr(long threadpoolPtr) {
32 | this.threadpoolPtr = threadpoolPtr;
33 | }
34 |
35 | private native boolean init(int nthreads);
36 |
37 | private static boolean isWindows32() {
38 |
39 | return ( OS.indexOf("win") >= 0 && "32".equals(System.getProperty("sun.arch.data.model")) );
40 |
41 | }
42 |
43 | private static boolean isWindows64() {
44 |
45 | return (OS.indexOf("win") >= 0 && "64".equals(System.getProperty("sun.arch.data.model")));
46 |
47 | }
48 |
49 | private static boolean isMac() {
50 |
51 | return (OS.indexOf("mac") >= 0);
52 |
53 | }
54 |
55 | private static boolean isUnix() {
56 |
57 | return (OS.indexOf("nix") >= 0 || OS.indexOf("nux") >= 0 || OS.indexOf("aix") > 0 );
58 |
59 | }
60 |
61 | private static boolean isSolaris() {
62 |
63 | return (OS.indexOf("sunos") >= 0);
64 |
65 | }
66 |
67 | static {
68 | try {
69 | if (isWindows32()) {
70 | NativeUtils.loadLibraryFromJar("/VS32.dll");
71 | } else if (isWindows64()) {
72 | // System.load("C:\\msys64\\home\\woonsh\\git-project\\AtomicThreadPool\\x64\\Release\\AtomicThreadPool.dll");
73 | NativeUtils.loadLibraryFromJar("/VS64.dll");
74 | } else if(isMac()){
75 | // Pending build from source
76 | logger.warning(" Mac is not support yet....");
77 | // NativeUtils.loadLibraryFromJar("/libatpool_jni.dylib");
78 | } else {
79 | NativeUtils.loadLibraryFromJar("/libatpool_jni.so");
80 | }
81 | } catch (IOException e) {
82 | e.printStackTrace(); // This is probably not the best way to handle exception :-)
83 | } catch (UnsatisfiedLinkError e) {
84 | /** It could be no dependencies found, load full pack **/
85 | logger.warning(" no dependencies found, load full pack library....");
86 | try {
87 | if (isWindows32()) {
88 | NativeUtils.loadLibraryFromJar("/VS32_full.dll");
89 | } else if (isWindows64()) {
90 | NativeUtils.loadLibraryFromJar("/VS64_full.dll");
91 | } else if(isMac()){
92 | logger.warning(" Mac is not support yet....");
93 | // NativeUtils.loadLibraryFromJar("/libatpool_jni.dylib");
94 | } else {
95 | NativeUtils.loadLibraryFromJar("/libatpool_jni.so");
96 | }
97 | } catch (IOException xe) {
98 | }
99 | }
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/java_source/src/main/java/com/github/taymindis/AtomicThreadPoolTask.java:
--------------------------------------------------------------------------------
1 | package com.github.taymindis;
2 |
3 | /**
4 | * Created by woonsh on 10/9/2018.
5 | */
6 | public interface AtomicThreadPoolTask {
7 |
8 | void runTask();
9 | }
10 |
--------------------------------------------------------------------------------
/java_source/src/main/java/com/github/taymindis/NativeUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Class NativeUtils is published under the The MIT License:
3 | *
4 | * Copyright (c) 2012 Adam Heinrich
5 | *
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy
7 | * of this software and associated documentation files (the "Software"), to deal
8 | * in the Software without restriction, including without limitation the rights
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | * copies of the Software, and to permit persons to whom the Software is
11 | * furnished to do so, subject to the following conditions:
12 | *
13 | * The above copyright notice and this permission notice shall be included in all
14 | * copies or substantial portions of the Software.
15 | *
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | * SOFTWARE.
23 | */
24 | package com.github.taymindis;
25 |
26 | import java.io.File;
27 | import java.io.FileNotFoundException;
28 | import java.io.IOException;
29 | import java.io.InputStream;
30 | import java.nio.file.*;
31 |
32 | /**
33 | * A simple library class which helps with loading dynamic libraries stored in the
34 | * JAR archive. These libraries usually contain implementation of some methods in
35 | * native code (using JNI - Java Native Interface).
36 | *
37 | * @see http://adamheinrich.com/blog/2012/how-to-load-native-jni-library-from-jar
38 | * @see https://github.com/adamheinrich/native-utils
39 | *
40 | */
41 | public class NativeUtils {
42 |
43 | /**
44 | * The minimum length a prefix for a file has to have according to {@link File#createTempFile(String, String)}}.
45 | */
46 | private static final int MIN_PREFIX_LENGTH = 3;
47 | public static final String NATIVE_FOLDER_PATH_PREFIX = "nativeutils";
48 |
49 | /**
50 | * Temporary directory which will contain the DLLs.
51 | */
52 | private static File temporaryDir;
53 |
54 | /**
55 | * Private constructor - this class will never be instanced
56 | */
57 | private NativeUtils() {
58 | }
59 |
60 | /**
61 | * Loads library from current JAR archive
62 | *
63 | * The file from JAR is copied into system temporary directory and then loaded. The temporary file is deleted after
64 | * exiting.
65 | * Method uses String as filename because the pathname is "abstract", not system-dependent.
66 | *
67 | * @param path The path of file inside JAR as absolute path (beginning with '/'), e.g. /package/File.ext
68 | * @throws IOException If temporary file creation or read/write operation fails
69 | * @throws IllegalArgumentException If source file (param path) does not exist
70 | * @throws IllegalArgumentException If the path is not absolute or if the filename is shorter than three characters
71 | * (restriction of {@link File#createTempFile(String, String)}).
72 | * @throws FileNotFoundException If the file could not be found inside the JAR.
73 | */
74 | public static void loadLibraryFromJar(String path) throws IOException, UnsatisfiedLinkError {
75 |
76 | if (null == path || !path.startsWith("/")) {
77 | throw new IllegalArgumentException("The path has to be absolute (start with '/').");
78 | }
79 |
80 | // Obtain filename from path
81 | String[] parts = path.split("/");
82 | String filename = (parts.length > 1) ? parts[parts.length - 1] : null;
83 |
84 | // Check if the filename is okay
85 | if (filename == null || filename.length() < MIN_PREFIX_LENGTH) {
86 | throw new IllegalArgumentException("The filename has to be at least 3 characters long.");
87 | }
88 |
89 | // Prepare temporary file
90 | if (temporaryDir == null) {
91 | temporaryDir = createTempDirectory(NATIVE_FOLDER_PATH_PREFIX);
92 | temporaryDir.deleteOnExit();
93 | }
94 |
95 | File temp = new File(temporaryDir, filename);
96 | InputStream is;
97 | try {
98 | is = NativeUtils.class.getResourceAsStream(path);
99 | Files.copy(is, temp.toPath(), StandardCopyOption.REPLACE_EXISTING);
100 | } catch (IOException e) {
101 | temp.delete();
102 | throw e;
103 | } catch (NullPointerException e) {
104 | temp.delete();
105 | throw new FileNotFoundException("File " + path + " was not found inside JAR.");
106 | }
107 |
108 | temp.setReadable(true, false);
109 |
110 | try {
111 | System.load(temp.getAbsolutePath());
112 | } finally {
113 | if (isPosixCompliant()) {
114 | // Assume POSIX compliant file system, can be deleted after loading
115 | temp.delete();
116 | } else {
117 | // Assume non-POSIX, and don't delete until last file descriptor closed
118 | temp.deleteOnExit();
119 | }
120 | }
121 | }
122 |
123 | private static boolean isPosixCompliant() {
124 | try {
125 | return FileSystems.getDefault()
126 | .supportedFileAttributeViews()
127 | .contains("posix");
128 | } catch (FileSystemNotFoundException e) {
129 | return false;
130 | } catch (ProviderNotFoundException e) {
131 | return false;
132 | } catch (SecurityException e) {
133 | return false;
134 | }
135 | }
136 |
137 | private static File createTempDirectory(String prefix) throws IOException {
138 | String tempDir = System.getProperty("java.io.tmpdir");
139 | File generatedDir = new File(tempDir, prefix + System.nanoTime());
140 |
141 | if (!generatedDir.mkdir())
142 | throw new IOException("Failed to create temp directory " + generatedDir.getName());
143 | generatedDir.setReadable(true, false);
144 | return generatedDir;
145 | }
146 | }
147 |
--------------------------------------------------------------------------------
/java_source/src/main/resources/VS32.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Taymindis/atomic_threadpool/d77f3b1d1d2e6277645d24dd6fb78cb4d1afa039/java_source/src/main/resources/VS32.dll
--------------------------------------------------------------------------------
/java_source/src/main/resources/VS32_full.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Taymindis/atomic_threadpool/d77f3b1d1d2e6277645d24dd6fb78cb4d1afa039/java_source/src/main/resources/VS32_full.dll
--------------------------------------------------------------------------------
/java_source/src/main/resources/VS64.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Taymindis/atomic_threadpool/d77f3b1d1d2e6277645d24dd6fb78cb4d1afa039/java_source/src/main/resources/VS64.dll
--------------------------------------------------------------------------------
/java_source/src/main/resources/VS64_full.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Taymindis/atomic_threadpool/d77f3b1d1d2e6277645d24dd6fb78cb4d1afa039/java_source/src/main/resources/VS64_full.dll
--------------------------------------------------------------------------------
/java_source/src/main/resources/libatpool_jni.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Taymindis/atomic_threadpool/d77f3b1d1d2e6277645d24dd6fb78cb4d1afa039/java_source/src/main/resources/libatpool_jni.so
--------------------------------------------------------------------------------
/java_source/src/test/java/com/github/taymindis/test/MyTask.java:
--------------------------------------------------------------------------------
1 | package com.github.taymindis.test;
2 |
3 | import com.github.taymindis.AtomicThreadPoolTask;
4 |
5 | import java.util.concurrent.atomic.AtomicInteger;
6 |
7 | /**
8 | * Created by woonsh on 10/9/2018.
9 | */
10 | public class MyTask implements AtomicThreadPoolTask {
11 |
12 | int a = -1;
13 | static AtomicInteger totalRun = null;
14 |
15 | public MyTask(int a) {
16 | if(totalRun == null) {
17 | totalRun = new AtomicInteger(0);
18 | }
19 | this.a = a;
20 | }
21 |
22 | public int getA() {
23 | return a;
24 | }
25 |
26 | public void setA(int a) {
27 | this.a = a;
28 | }
29 |
30 | public void runTask() {
31 | totalRun.getAndIncrement();
32 | System.out.println("Task is running at " + a + " with thread id " + Thread.currentThread().getId());
33 | }
34 |
35 | public static AtomicInteger getTotalRun() {
36 | return totalRun;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/java_source/src/test/java/com/github/taymindis/test/Test1.java:
--------------------------------------------------------------------------------
1 | package com.github.taymindis.test;
2 |
3 | import java.io.IOException;
4 |
5 | import com.github.taymindis.AtomicThreadPool;
6 | import org.junit.Test;
7 | import static org.junit.Assert.*;
8 | /**
9 | * Created by woonsh on 10/9/2018.
10 | */
11 | public class Test1 {
12 |
13 | @Test
14 | public void testRun() throws IOException, InterruptedException {
15 | System.out.println("Thread pool is running in 2 sec");
16 | Thread.sleep(2000);
17 | AtomicThreadPool p = new AtomicThreadPool(8);
18 |
19 | for(int i=0; i< 1000; i++) {
20 | assertTrue(p.newTask(new MyTask(i)));
21 | }
22 |
23 | Thread.sleep(3000);
24 | assertTrue(MyTask.getTotalRun().intValue() == 1000);
25 |
26 | p.shutdown();
27 | }
28 |
29 | }
30 |
--------------------------------------------------------------------------------
/jni-cross-platform/AtomicThreadPool.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | //#include
8 | #include
9 |
10 | #define callStaticByMethod$(returnType, env, clazz, methodName, sig) \
11 | (*env)->CallStatic##returnType##Method(env,clazz, (*env)->GetStaticMethodID(env, clazz, methodName, sig))
12 | #define callStaticByMethod$2(returnType, env, clazz, methodName, sig, ... ) \
13 | (*env)->CallStatic##returnType##Method(env,clazz, (*env)->GetStaticMethodID(env, clazz, methodName, sig), __VA_ARGS__)
14 |
15 | #define callStaticByField$(returnType, env, clazz, fieldName, sig ) \
16 | (*env)->GetStatic##returnType##Field(env, clazz, (*env)->GetStaticFieldID(env, clazz, fieldName, sig))
17 |
18 | #define callByMethod$(returnType, env, clazz, obj$, methodName, sig ) \
19 | (*env)->Call##returnType##Method(env, obj$, (*env)->GetMethodID(env, clazz, methodName, sig))
20 | #define callByMethod$2(returnType, env, clazz, obj$, methodName, sig, ... ) \
21 | (*env)->Call##returnType##Method(env, obj$, (*env)->GetMethodID(env, clazz, methodName, sig), __VA_ARGS__)
22 |
23 | #define callByField$(returnType, env, clazz, obj$, fieldName, sig ) \
24 | (*env)->Get##returnType##Field(env, obj$, (*env)->GetFieldID(env,clazz, fieldName, sig))
25 |
26 | static JavaVM *jvm = NULL; // Pointer to the JVM (Java Virtual Machine)
27 | //static JNIEnv *_env = NULL;
28 | void update_curr_jvm(JNIEnv *env);
29 |
30 | void runTask_(void* arg) {
31 | JNIEnv * _env;
32 | jint rs, getEnvStat = (*jvm)->GetEnv(jvm, (void **)&_env, JNI_VERSION_1_6);
33 | if (getEnvStat == JNI_EDETACHED) {
34 | // No attached, attached now
35 | rs = (*jvm)->AttachCurrentThread(jvm, (void**)&_env, NULL);
36 | assert(rs == JNI_OK);
37 | }
38 |
39 | jobject refThreadObj = (jobject)arg;
40 | jclass clz = (*_env)->GetObjectClass(_env, refThreadObj);
41 | callByMethod$(Void, _env, clz, refThreadObj, "runTask", "()V");
42 |
43 | (*_env)->DeleteGlobalRef(_env, refThreadObj);
44 | (*_env)->DeleteLocalRef(_env, clz);
45 |
46 | rs = (*jvm)->DetachCurrentThread(jvm);
47 | assert(rs == JNI_OK);
48 | }
49 |
50 | JNIEXPORT jboolean JNICALL Java_com_github_taymindis_AtomicThreadPool_init(JNIEnv *env, jobject obj, jint nthreads) {
51 | if (jvm == NULL) {
52 | //_env = env;
53 | update_curr_jvm(env);
54 | }
55 | jclass clz = (*env)->GetObjectClass(env, obj);
56 | printf("%s, %d\n", "Intializing threadpool", nthreads);
57 | at_thpool_t *thpool = at_thpool_create(nthreads);
58 |
59 | callByMethod$2(Void, env, clz, obj, "setThreadpoolPtr", "(J)V", (jlong)thpool);
60 |
61 | /****
62 | * Local references are garbage collected when the native function returns to Java (when Java calls native)
63 | * or when the calling thread is detached from the JVM (in native calls Java).
64 | * You need explicit DeleteLocalRef only when you have a long lived native function
65 | * (e.g., a main loop) or create a large number of transient objects in a loop
66 | * Since you are return JNI true, DeleteLocalRef is not necessary at this point.
67 | ****/
68 |
69 | (*env)->DeleteLocalRef(env, clz);
70 |
71 |
72 | return JNI_TRUE;
73 | }
74 |
75 | JNIEXPORT jboolean JNICALL Java_com_github_taymindis_AtomicThreadPool_newTask(JNIEnv *env, jobject obj, jobject threadObj) {
76 | jclass clz = (*env)->GetObjectClass(env, obj);
77 | at_thpool_t *thpool = (at_thpool_t *)callByField$(Long, env, clz, obj, "threadpoolPtr", "J");
78 | jobject refObj = (*env)->NewGlobalRef(env, threadObj);
79 | if (thpool != NULL && thpool > 0) {
80 | if (at_thpool_newtask(thpool, runTask_, refObj) != -1) {
81 | return JNI_TRUE;
82 | }
83 | }
84 | printf("The pool has not initialized yet");
85 | (*env)->DeleteLocalRef(env, clz);
86 | return JNI_FALSE;
87 | }
88 |
89 | JNIEXPORT void JNICALL Java_com_github_taymindis_AtomicThreadPool_shutdown(JNIEnv *env, jobject obj) {
90 | jclass clz = (*env)->GetObjectClass(env, obj);
91 | at_thpool_t *thpool =(at_thpool_t *) callByMethod$(Long, env, clz, obj, "getThreadpoolPtr", "()J");
92 | if (thpool != NULL && thpool > 0) {
93 | at_thpool_gracefully_shutdown(thpool);
94 | }
95 | (*env)->DeleteLocalRef(env, clz);
96 | }
97 |
98 | void update_curr_jvm(JNIEnv *env) {
99 | if (!(*env)->GetJavaVM(env, &jvm) < 0) {
100 | return;
101 | }
102 | jint ver = (*env)->GetVersion(env); // (*env)->GetVersion();
103 | //cout << ((ver >> 16) & 0x0f) << "." << (ver & 0x0f) ;
104 | //jobject a = callStaticByMethod$2(Object, env, cls2, "getTag", "(I)LTestIvd;", 2); //(*env)->CallStaticObjectMethod(cls2, getTagStaicMethodId, 1);
105 |
106 | //cout << "Field tag id is " << callByMethod$(Int, env, cls2, a, "getId", "()I") << "\n";
107 | printf("Version is %d\n", ver);
108 | }
109 |
110 |
111 |
--------------------------------------------------------------------------------
/jni-cross-platform/AtomicThreadPool.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #ifndef _ATOMIC_THREADPOOL_H
3 | #define _ATOMIC_THREADPOOL_H
4 |
5 | #include
6 |
7 | #ifdef __cplusplus
8 | extern "C" {
9 | #endif
10 |
11 | JNIEXPORT jboolean JNICALL Java_com_github_taymindis_AtomicThreadPool_init(JNIEnv *env, jobject obj, jint nthreads);
12 | JNIEXPORT jboolean JNICALL Java_com_github_taymindis_AtomicThreadPool_newTask(JNIEnv *env, jobject obj, jobject threadObj);
13 | JNIEXPORT void JNICALL Java_com_github_taymindis_AtomicThreadPool_shutdown(JNIEnv *env, jobject obj);
14 |
15 | #ifdef __cplusplus
16 | }
17 | #endif
18 |
19 | #endif
--------------------------------------------------------------------------------
/threadpool_example.c:
--------------------------------------------------------------------------------
1 |
2 | #include
3 | #if defined __GNUC__ || defined __CYGWIN__ || defined __MINGW32__ || defined __APPLE__
4 | #include
5 | #elif defined _WIN32 || _WIN64
6 | #include
7 | #include
8 | #endif
9 | #include "at_thpool.h"
10 |
11 |
12 | #define TASK_SIZE 200
13 |
14 | void t1(void *arg);
15 | void t2(void *arg);
16 | void t3(void *arg);
17 | void t4(void *arg);
18 |
19 | void t1(void *arg) {
20 | printf("t1 is running on thread \n");
21 | }
22 |
23 | void t2(void *arg) {
24 | printf("t2 is running on thread \n");
25 | }
26 |
27 | void t3(void *arg) {
28 | printf("t3 is running on thread \n");
29 | }
30 |
31 | void t4(void *arg) {
32 | printf("t4 is running on thread \n");
33 | }
34 |
35 | int main(void) {
36 | int nthreads = 8;//sysconf(_SC_NPROCESSORS_ONLN); // Linux
37 |
38 | printf("Share thread pool with %d threads with at lease totalthroughput * nthreads task size\n", nthreads);
39 | at_thpool_t *thpool = at_thpool_create(nthreads);
40 |
41 | printf("assigned %d tasks between %d threads\n", TASK_SIZE, nthreads);
42 | int i;
43 | for (i = 0; i < TASK_SIZE; i++) {
44 | at_thpool_newtask(thpool, t1, NULL);
45 | at_thpool_newtask(thpool, t2, NULL);
46 | at_thpool_newtask(thpool, t3, NULL);
47 | at_thpool_newtask(thpool, t4, NULL);
48 | }
49 |
50 | #if defined _WIN32 || _WIN64
51 | Sleep(1000);
52 | #else
53 | sleep(1);
54 | #endif
55 |
56 | puts("shutdown thread pool");
57 | at_thpool_gracefully_shutdown(thpool);
58 |
59 | return 0;
60 | }
--------------------------------------------------------------------------------