├── .gitignore
├── .idea
├── .gitignore
├── compiler.xml
├── gradle.xml
├── jarRepositories.xml
├── misc.xml
└── vcs.xml
├── app
├── .DS_Store
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── .DS_Store
│ └── main
│ ├── .DS_Store
│ ├── AndroidManifest.xml
│ ├── cpp
│ ├── .DS_Store
│ ├── CMakeLists.txt
│ ├── ConcurrenceQueue.h
│ ├── CoroutineDespatcher.cpp
│ ├── CoroutineDespatcher.h
│ ├── OSCoroutine.cpp
│ ├── OSCoroutine.h
│ ├── OSThread.cpp
│ ├── OSThread.h
│ ├── log.h
│ └── native-lib.cpp
│ ├── java
│ └── com
│ │ └── kymjs
│ │ ├── coroutine
│ │ ├── Coroutine.java
│ │ └── MainActivity.kt
│ │ └── thread
│ │ └── LiteThread.java
│ └── res
│ ├── .DS_Store
│ ├── drawable-v24
│ └── ic_launcher_foreground.xml
│ ├── drawable
│ └── ic_launcher_background.xml
│ ├── layout
│ └── activity_main.xml
│ ├── mipmap-anydpi-v26
│ ├── ic_launcher.xml
│ └── ic_launcher_round.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.webp
│ └── ic_launcher_round.webp
│ ├── mipmap-mdpi
│ ├── ic_launcher.webp
│ └── ic_launcher_round.webp
│ ├── mipmap-xhdpi
│ ├── ic_launcher.webp
│ └── ic_launcher_round.webp
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.webp
│ └── ic_launcher_round.webp
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.webp
│ └── ic_launcher_round.webp
│ ├── values-night
│ └── themes.xml
│ └── values
│ ├── colors.xml
│ ├── strings.xml
│ └── themes.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.aar
4 | *.ap_
5 | *.aab
6 |
7 | # Files for the ART/Dalvik VM
8 | *.dex
9 |
10 | # Java class files
11 | *.class
12 |
13 | # Generated files
14 | bin/
15 | gen/
16 | out/
17 | # Uncomment the following line in case you need and you don't have the release build type files in your app
18 | # release/
19 |
20 | # Gradle files
21 | .gradle/
22 | build/
23 |
24 | # Local configuration file (sdk path, etc)
25 | local.properties
26 |
27 | # Proguard folder generated by Eclipse
28 | proguard/
29 |
30 | # Log Files
31 | *.log
32 |
33 | # Android Studio Navigation editor temp files
34 | .navigation/
35 |
36 | # Android Studio captures folder
37 | captures/
38 |
39 | # IntelliJ
40 | *.iml
41 | .idea/workspace.xml
42 | .idea/tasks.xml
43 | .idea/gradle.xml
44 | .idea/assetWizardSettings.xml
45 | .idea/dictionaries
46 | .idea/libraries
47 | # Android Studio 3 in .gitignore file.
48 | .idea/caches
49 | .idea/modules.xml
50 | # Comment next line if keeping position of elements in Navigation Editor is relevant for you
51 | .idea/navEditor.xml
52 |
53 | # Keystore files
54 | # Uncomment the following lines if you do not want to check your keystore files in.
55 | #*.jks
56 | #*.keystore
57 |
58 | # External native build folder generated in Android Studio 2.2 and later
59 | .externalNativeBuild
60 | .cxx/
61 |
62 | # Google Services (e.g. APIs or Firebase)
63 | # google-services.json
64 |
65 | # Freeline
66 | freeline.py
67 | freeline/
68 | freeline_project_description.json
69 |
70 | # fastlane
71 | fastlane/report.xml
72 | fastlane/Preview.html
73 | fastlane/screenshots
74 | fastlane/test_output
75 | fastlane/readme.md
76 |
77 | # Version control
78 | vcs.xml
79 |
80 | # lint
81 | lint/intermediates/
82 | lint/generated/
83 | lint/outputs/
84 | lint/tmp/
85 | # lint/reports/
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
19 |
20 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kymjs/AndroidCoroutine/0899aa345abd22429d3f992664981c0987902853/app/.DS_Store
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 |
4 | android {
5 | compileSdk 30
6 |
7 | defaultConfig {
8 | applicationId "com.kymjs.coroutine"
9 | minSdk 21
10 | targetSdk 30
11 | versionCode 1
12 | versionName "1.0"
13 |
14 | externalNativeBuild {
15 | cmake {
16 | cppFlags '-std=c++11'
17 | // arguments "-DANDROID_ARM_NEON=TRUE"
18 | }
19 | }
20 | }
21 |
22 | buildTypes {
23 | release {
24 | minifyEnabled false
25 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
26 | }
27 | }
28 | compileOptions {
29 | sourceCompatibility JavaVersion.VERSION_1_8
30 | targetCompatibility JavaVersion.VERSION_1_8
31 | }
32 | externalNativeBuild {
33 | cmake {
34 | path file('src/main/cpp/CMakeLists.txt')
35 | version '3.10.2'
36 | }
37 | }
38 | buildFeatures {
39 | viewBinding true
40 | }
41 | }
42 |
43 | dependencies {
44 | implementation 'androidx.appcompat:appcompat:1.2.0'
45 | implementation 'com.google.android.material:material:1.3.0'
46 | implementation "androidx.core:core-ktx:1.3.2"
47 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
48 | }
49 | repositories {
50 | mavenCentral()
51 | }
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kymjs/AndroidCoroutine/0899aa345abd22429d3f992664981c0987902853/app/src/.DS_Store
--------------------------------------------------------------------------------
/app/src/main/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kymjs/AndroidCoroutine/0899aa345abd22429d3f992664981c0987902853/app/src/main/.DS_Store
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
14 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/cpp/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kymjs/AndroidCoroutine/0899aa345abd22429d3f992664981c0987902853/app/src/main/cpp/.DS_Store
--------------------------------------------------------------------------------
/app/src/main/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.10.2)
2 | project("coroutine")
3 |
4 | #ENABLE_LANGUAGE(ASM)
5 |
6 | add_library(
7 | coroutine
8 | SHARED
9 | native-lib.cpp
10 | OSCoroutine.cpp
11 | OSThread.cpp
12 | CoroutineDespatcher.cpp)
13 |
14 | find_library(
15 | log-lib
16 | log)
17 |
18 | target_link_libraries(
19 | coroutine
20 | ${log-lib})
--------------------------------------------------------------------------------
/app/src/main/cpp/ConcurrenceQueue.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zhangtao on 2022/2/15.
3 | //
4 |
5 | #ifndef COROUTINE_CONCURRENCEQUEUE_H
6 | #define COROUTINE_CONCURRENCEQUEUE_H
7 |
8 |
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | template
15 | class ConcurrenceQueue {
16 | private:
17 | // data_queue访问信号量
18 | mutable std::mutex mut;
19 | mutable std::condition_variable data_cond;
20 | using queue_type = std::deque;
21 | queue_type data_queue;
22 | public:
23 | using value_type = typename queue_type::value_type;
24 |
25 | ConcurrenceQueue() = default;
26 |
27 | ConcurrenceQueue(const ConcurrenceQueue &) = delete;
28 |
29 | ConcurrenceQueue &operator=(const ConcurrenceQueue &) = delete;
30 |
31 | /*
32 | * 使用迭代器为参数的构造函数,适用所有容器对象
33 | * */
34 | template
35 | ConcurrenceQueue(_InputIterator
36 | first,
37 | _InputIterator last
38 | ) {
39 | for (auto itor = first; itor != last; ++itor) {
40 | data_queue.push(*itor);
41 | }
42 | }
43 |
44 | /*
45 | * 使用初始化列表为参数的构造函数
46 | * */
47 | ConcurrenceQueue(std::initializer_list list) : ConcurrenceQueue(list.begin(), list.end()) {
48 | }
49 |
50 | /*
51 | * 将元素加入队列
52 | * */
53 | void push(const value_type &new_value) {
54 | std::lock_guard lk(mut);
55 | data_queue.push_back(std::move(new_value));
56 | data_cond.notify_one();
57 | }
58 |
59 | /*
60 | * 将元素加入队列头
61 | * */
62 | void push_front(const value_type &value1, const value_type &value2) {
63 | std::lock_guard lk(mut);
64 | data_queue.push_front(std::move(value1));
65 | data_queue.push_front(std::move(value2));
66 | data_cond.notify_one();
67 | }
68 |
69 | void push_front(const value_type &new_value) {
70 | std::lock_guard lk(mut);
71 | data_queue.push_front(std::move(new_value));
72 | data_cond.notify_one();
73 | }
74 |
75 | /*
76 | * 从队列中弹出一个元素,如果队列为空就阻塞
77 | * */
78 | value_type pop() {
79 | std::unique_lock lk(mut);
80 | data_cond.wait(lk, [this] { return !this->data_queue.empty(); });
81 | auto value = std::move(data_queue.front());
82 | data_queue.pop_front();
83 | return value;
84 | }
85 |
86 | /*
87 | * 从队列尾弹出一个元素,如果队列为空就阻塞
88 | * */
89 | value_type pop_back() {
90 | std::unique_lock lk(mut);
91 | data_cond.wait(lk, [this] { return !this->data_queue.empty(); });
92 | auto value = std::move(data_queue.front());
93 | data_queue.pop_back();
94 | return value;
95 | }
96 |
97 | /*
98 | * 从队列中弹出一个元素,如果队列为空返回false
99 | * */
100 | bool try_pop(value_type &value) {
101 | std::lock_guard lk(mut);
102 | if (data_queue.empty())
103 | return false;
104 | value = std::move(data_queue.front());
105 | data_queue.pop_front();
106 | return true;
107 | }
108 |
109 | /*
110 | * 返回队列是否为空
111 | * */
112 | auto empty() const -> decltype(data_queue.empty()) {
113 | std::lock_guard lk(mut);
114 | return data_queue.empty();
115 | }
116 |
117 | /*
118 | * 返回队列中元素数个
119 | * */
120 | auto size() const -> decltype(data_queue.size()) {
121 | std::lock_guard lk(mut);
122 | return data_queue.size();
123 | }
124 | };
125 |
126 | #endif //COROUTINE_CONCURRENCEQUEUE_H
127 |
--------------------------------------------------------------------------------
/app/src/main/cpp/CoroutineDespatcher.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zhangtao on 2022/2/11.
3 | //
4 |
5 | #include "CoroutineDespatcher.h"
6 |
7 | CoroutineDespatcher::CoroutineDespatcher(JNIEnv *env, bool mainThread) {
8 | env->GetJavaVM(&(this->jvm));
9 | this->mainThread = mainThread;
10 | this->env = env;
11 | }
12 |
13 | CoroutineDespatcher::~CoroutineDespatcher() {
14 | jvm->DetachCurrentThread();
15 | }
16 |
17 | void CoroutineDespatcher::despatchInMainThread(OSCoroutine *pCoroutine) {
18 | if (pCoroutine != nullptr) {
19 | pCoroutine->async(env);
20 | delete pCoroutine;
21 | }
22 | }
23 |
24 | void CoroutineDespatcher::despatch() {
25 | while (!mainThread) {
26 | if (suspendQueue.empty()) {
27 | fightCoroutine = fightQueue.pop();
28 | if (fightCoroutine->suspendState == NONE) {
29 | LOGD("====fightQueue->执行协程%lld", fightCoroutine->coroutineId);
30 | fightCoroutine->async(env);
31 | if (fightCoroutine->suspendState == FINISHED) {
32 | delete fightCoroutine;
33 | }
34 | }
35 | } else {
36 | if (suspendQueue.try_pop(fightCoroutine)) {
37 | if (fightCoroutine->suspendState < RESUMED) {
38 | LOGD("====suspendQueue->执行协程%lld", fightCoroutine->coroutineId);
39 | fightCoroutine->async(env);
40 | }
41 |
42 | if (fightCoroutine->suspendState == FINISHED) {
43 | delete fightCoroutine;
44 | }
45 | }
46 | }
47 | }
48 | }
49 |
50 | void CoroutineDespatcher::join(jobject jobj) {
51 | if (mainThread) {
52 | despatchInMainThread(new OSCoroutine(env, jobj));
53 | } else {
54 | if (fightCoroutine != nullptr) {
55 | fightCoroutine->suspendState = SUSPEND;
56 | suspendQueue.push_front(fightCoroutine, new OSCoroutine(env, jobj));
57 | } else {
58 | suspendQueue.push_front(new OSCoroutine(env, jobj));
59 | }
60 | }
61 | }
62 |
63 | void CoroutineDespatcher::attachCoroutine(jobject jobj) {
64 | if (mainThread) {
65 | despatchInMainThread(new OSCoroutine(env, jobj));
66 | } else {
67 | fightQueue.push(new OSCoroutine(env, jobj));
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/cpp/CoroutineDespatcher.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zhangtao on 2022/2/11.
3 | //
4 |
5 | #ifndef COROUTINE_THREAD_H
6 | #define COROUTINE_THREAD_H
7 |
8 | #include
9 | #include "ConcurrenceQueue.h"
10 | #include "pthread.h"
11 | #include "OSCoroutine.h"
12 | #include "log.h"
13 |
14 | class CoroutineDespatcher {
15 | private:
16 | ConcurrenceQueue fightQueue;
17 | ConcurrenceQueue suspendQueue;
18 | OSCoroutine *fightCoroutine;
19 | bool mainThread;
20 | JNIEnv *env;
21 |
22 | void despatchInMainThread(OSCoroutine *pCoroutine);
23 |
24 | public:
25 | JavaVM *jvm;
26 |
27 | ~CoroutineDespatcher();
28 |
29 | CoroutineDespatcher(JNIEnv *env, bool mainThread);
30 |
31 | void despatch();
32 |
33 | void join(jobject jobj);
34 |
35 | void attachCoroutine(jobject jobj);
36 | };
37 |
38 | #endif //COROUTINE_THREAD_H
39 |
--------------------------------------------------------------------------------
/app/src/main/cpp/OSCoroutine.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zhangtao on 2022/2/14.
3 | //
4 |
5 | #include "OSCoroutine.h"
6 |
7 | OSCoroutine::OSCoroutine(JNIEnv *env, jobject jobj) {
8 | env->GetJavaVM(&(this->jvm));
9 | this->jCoroutine = env->NewGlobalRef(jobj);
10 | jclass jCoroutineClass = env->GetObjectClass(jCoroutine);
11 | jfieldID jCoroutineId = env->GetFieldID(jCoroutineClass, "coroutineId", "J");
12 | this->coroutineId = env->GetLongField(jCoroutine, jCoroutineId);
13 | }
14 |
15 | OSCoroutine::~OSCoroutine() {
16 | }
17 |
18 | void OSCoroutine::async(JNIEnv *env) {
19 | if (suspendState == NEED_RESUME) {
20 | resume(env);
21 | } else {
22 | suspendState = NONE;
23 | if (jvm->AttachCurrentThread(&env, NULL) != 0) {
24 | LOGD("faile to attach");
25 | }
26 |
27 | jclass jCoroutineClass = env->GetObjectClass(jCoroutine);
28 | jmethodID runId = env->GetMethodID(jCoroutineClass, "run", "()Ljava/lang/Object;");
29 | if (runId != nullptr) {
30 | suspendAwait(env, env->CallObjectMethod(jCoroutine, runId));
31 | } else {
32 | LOGD("No run method found in Coroutine");
33 | }
34 | }
35 | }
36 |
37 | void OSCoroutine::suspendAwait(JNIEnv *env, jobject result) {
38 | if (suspendState == SUSPEND) {
39 | if (setjmp(suspendPoint)) {
40 | await(env, result);
41 | } else {
42 | suspendState = NEED_RESUME;
43 | LOGD("挂起协程:%lld", coroutineId);
44 | }
45 | } else if (suspendState == NONE) {
46 | await(env, result);
47 | }
48 | }
49 |
50 | void OSCoroutine::await(JNIEnv *env, jobject result) {
51 | jclass jCoroutineClass = env->GetObjectClass(jCoroutine);
52 | jmethodID onAwaitMethod = env->GetMethodID(jCoroutineClass, "onAwait", "(Ljava/lang/Object;)V");
53 | if (onAwaitMethod != nullptr) {
54 | env->CallVoidMethod(jCoroutine, onAwaitMethod, result);
55 | }
56 | suspendState = FINISHED;
57 | LOGD("协程:%lld,执行完成", coroutineId);
58 | env->DeleteGlobalRef(jCoroutine);
59 | }
60 |
61 | void OSCoroutine::delay(jlong millis) {
62 |
63 | }
64 |
65 | void OSCoroutine::resume(JNIEnv *env) {
66 | LOGD("恢复协程%lld", coroutineId);
67 | suspendState = RESUMED;
68 | longjmp(suspendPoint, 1);
69 | }
70 |
--------------------------------------------------------------------------------
/app/src/main/cpp/OSCoroutine.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zhangtao on 2022/2/14.
3 | //
4 |
5 | #ifndef COROUTINE_OSCOROUTINE_H
6 | #define COROUTINE_OSCOROUTINE_H
7 |
8 |
9 | #include
10 | #include "log.h"
11 | #include
12 |
13 | const int NONE = 0;
14 | const int SUSPEND = 1;
15 | const int NEED_RESUME = 2;
16 | const int RESUMED = 3;
17 | const int FINISHED = 4;
18 |
19 | class OSCoroutine {
20 | private:
21 | jmp_buf suspendPoint;
22 | public:
23 | JavaVM *jvm;
24 | jobject jCoroutine;
25 | jlong coroutineId;
26 | int suspendState = NONE;
27 |
28 | ~OSCoroutine();
29 |
30 | OSCoroutine(JNIEnv *env, jobject thiz);
31 |
32 | void async(JNIEnv *env);
33 |
34 | void await(JNIEnv *env, jobject result);
35 |
36 | void suspendAwait(JNIEnv *env, jobject result);
37 |
38 | void delay(jlong millis);
39 |
40 | void resume(JNIEnv *env);
41 | };
42 |
43 |
44 | #endif //COROUTINE_OSCOROUTINE_H
45 |
--------------------------------------------------------------------------------
/app/src/main/cpp/OSThread.cpp:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zhangtao on 2022/2/11.
3 | //
4 |
5 | #include "log.h"
6 | #include "OSThread.h"
7 |
8 | OSThread::OSThread(JNIEnv *env, long threadId) {
9 | this->threadId = threadId;
10 | this->despatcher = new CoroutineDespatcher(env, threadId == 1);
11 | }
12 |
13 | OSThread::~OSThread() {
14 | delete despatcher;
15 | }
16 |
17 | void OSThread::start() {
18 | if (threadId == 1) {
19 | LOGD("在主线程执行协程");
20 | despatcher->despatch();
21 | } else {
22 | pthread_t tid;
23 | pthread_attr_t Attr;
24 | pthread_attr_init(&Attr);
25 | pthread_attr_setdetachstate(&Attr, PTHREAD_CREATE_DETACHED);
26 | if (pthread_create(&tid, &Attr, &OSThread::thread_entry_function, this->despatcher) != 0) {
27 | LOGD("线程创建失败");
28 | return;
29 | }
30 | LOGD("启动C线程 tid=%ld", tid);
31 | pthread_attr_destroy(&Attr);
32 | }
33 | }
34 |
35 | void *OSThread::thread_entry_function(void *args) {
36 | auto *despatcher = static_cast(args);
37 | despatcher->despatch();
38 | delete despatcher;
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/cpp/OSThread.h:
--------------------------------------------------------------------------------
1 | //
2 | // Created by zhangtao on 2022/2/11.
3 | //
4 |
5 | #ifndef COROUTINE_OSTHREAD_H
6 | #define COROUTINE_OSTHREAD_H
7 |
8 |
9 | #include "CoroutineDespatcher.h"
10 |
11 | class OSThread {
12 | public:
13 | long threadId;
14 | CoroutineDespatcher *despatcher;
15 |
16 | OSThread(JNIEnv *env, long threadId);
17 |
18 | ~OSThread();
19 |
20 | void start();
21 |
22 | static void *thread_entry_function(void *args);
23 | };
24 |
25 |
26 | #endif //COROUTINE_OSTHREAD_H
27 |
--------------------------------------------------------------------------------
/app/src/main/cpp/log.h:
--------------------------------------------------------------------------------
1 | #ifndef CORE_LOG_H
2 | #define CORE_LOG_H
3 |
4 | #define APP_NAME "com.kymjs.coroutine"
5 | #define DEBUG 1
6 |
7 | #ifdef __ANDROID__
8 |
9 | #include
10 | #include
11 |
12 | #ifdef DEBUG
13 | #define LOGV(...) __android_log_print(2, APP_NAME, __VA_ARGS__)
14 | #define LOGD(...) __android_log_print(3, APP_NAME, __VA_ARGS__)
15 | #define LOGI(...) __android_log_print(4, APP_NAME, __VA_ARGS__)
16 | #define LOGW(...) __android_log_print(5, APP_NAME, __VA_ARGS__)
17 | #define LOGE(...) __android_log_print(6, APP_NAME, __VA_ARGS__)
18 | #else
19 | #define LOGV(...) {}
20 | #define LOGD(...) {}
21 | #define LOGI(...) {}
22 | #define LOGW(...) {}
23 | #define LOGE(...) {}
24 | #endif
25 |
26 | #else // __ANDROID__
27 |
28 | ///================= package define =====================
29 | #define ARG_COUNT_PRIVATE(\
30 | _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, \
31 | _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \
32 | _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, \
33 | _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, \
34 | _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, \
35 | _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, \
36 | _60, _61, _62, _63, _64, N, ...) N
37 |
38 | #define ARG_COUNT(...) ARG_COUNT_PRIVATE(0, __VA_ARGS__,\
39 | 64, 63, 62, 61, 60, \
40 | 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, \
41 | 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, \
42 | 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, \
43 | 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
44 | 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
45 | 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
46 |
47 | #define FUN_COUNT_GLUE(M, count) M##count
48 | #define FUN_JOIN_COUNT(M, count) FUN_COUNT_GLUE(M,count)
49 | #define FUN_JOIN_ARGS(x, y) x y
50 |
51 | #define CallSomeOne(fn, ...) FUN_JOIN_ARGS(FUN_JOIN_COUNT(fn, ARG_COUNT(__VA_ARGS__)), (__VA_ARGS__))
52 |
53 | #if defined QS_LOG
54 | #include "QsLog.h"
55 | #define PR QLOG_INFO() // QsLog 输出(一个用Qt封装的日志类,挺好用的,在此推荐一下)
56 | #define ENDL ""
57 | #elif defined QT_CORE_LIB // Qt 标准输出
58 | #include
59 | #define PR qDebug()
60 | #define ENDL ""
61 | #elif defined __cplusplus
62 |
63 | #include
64 |
65 | using namespace std;
66 | #define PR std::cout
67 | #define ENDL std::endl
68 | #endif
69 |
70 | #define OUT_RED "\033[0;31;1m"
71 | #define OUT_GREEN "\033[0;32;1m"
72 | #define OUT_YELLOW "\033[0;33;1m"
73 | #define OUT_BLUE "\033[0;34;1m"
74 | #define OUT_END "\033[0m"
75 |
76 | #define FILE_INFO "[" << __FILE__ << '@' << __FUNCTION__ << '#' << __LINE__ << "]"
77 |
78 | #define param1(a) #a":" << a
79 | #define param2(a, b) #a":" << a << ", "#b":" << b
80 | #define param3(a, b, c) #a":" << a << ", "#b":" << b << ", "#c":" << c
81 | #define param4(a, b, c, d) #a":" << a << ", "#b":" << b << ", "#c":" << c << ", "#d":" << d
82 |
83 | #define pr0() "null param out"
84 | #define pr1(...) param1(__VA_ARGS__)
85 | #define pr2(...) param2(__VA_ARGS__)
86 | #define pr3(...) param3(__VA_ARGS__)
87 | #define pr4(...) param4(__VA_ARGS__)
88 | #define pr5(a, b, c, d, e) pr3(a,b,c) << ", " << param2(d,e)
89 | #define pr6(a, b, c, d, e, f) pr3(a,b,c) << ", " << param3(d,e,f)
90 | #define pr7(a, b, c, d, e, f, g) pr4(a,b,c,d) << ", " << param3(e,f,g)
91 | #define pr8(a, b, c, d, e, f, g, h) pr4(a,b,c,d) << ", " << param4(e,f,g,h)
92 | #define pr9(a, b, c, d, e, f, g, h, i) pr8(a,b,c,d,e,f,g,h) << ", " << param1(i)
93 | #define pr10(a, b, c, d, e, f, g, h, i, j) pr9(a,b,c,d,e,f,g,h,i) << ", " << param1(j)
94 | //.... 有兴趣可以继续扩充
95 |
96 | #define LOGV(x) PR << FILE_INFO << x << ENDL // 原样输出,无需格式化
97 |
98 | #define LOGD(...) PR << "" << "DEBUG " << FILE_INFO << CallSomeOne(pr, __VA_ARGS__) << ENDL
99 | #define LOGI(...) PR << OUT_GREEN << "INFO " << FILE_INFO << CallSomeOne(pr, __VA_ARGS__) << OUT_END << ENDL
100 | #define LOGW(...) PR << OUT_YELLOW << "WARN " << FILE_INFO << CallSomeOne(pr, __VA_ARGS__) << OUT_END << ENDL
101 | #define LOGE(...) PR << OUT_RED << "ERROR " << FILE_INFO << CallSomeOne(pr, __VA_ARGS__) << OUT_END << ENDL
102 | #endif // ANDROID_H
103 |
104 | #endif //CORE_LOG_H
105 |
106 |
--------------------------------------------------------------------------------
/app/src/main/cpp/native-lib.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include