Mercurial > dwindows
comparison android/dw.cpp @ 2801:b004cc75d574
Android: Remove the _DW_EVENT_THREADING experiment.
While it was more simple to launch a new thread to handle each event, this
approach had numerous drawbacks. No reasonable way to limit the number of
threads or memory consumed. Order of operations problems, the thread
scheduler would control the order in which the events were handled, not the
order of events produced by the UI.
The non-threaded version has been working and stable for a while now even
though it is more complicated for us to maintain our own event queue... this
allows us to make sure the events are handled in order and we can limit the
number of events in tight system resource situations.
author | bsmith@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Sun, 17 Jul 2022 21:03:31 +0000 |
parents | 0c534743b7a9 |
children | f910da0418f6 |
comparison
equal
deleted
inserted
replaced
2800:56eab3a84b62 | 2801:b004cc75d574 |
---|---|
34 | 34 |
35 #ifdef __cplusplus | 35 #ifdef __cplusplus |
36 extern "C" { | 36 extern "C" { |
37 #endif | 37 #endif |
38 | 38 |
39 /* Define this to enable threading for events... | |
40 * most Android events don't handle return values, so | |
41 * we can launch a new thread to handle the event. | |
42 * #define _DW_EVENT_THREADING | |
43 */ | |
44 /* #define _DW_EVENT_THREADING */ | |
45 #define DW_CLASS_NAME "org/dbsoft/dwindows/DWindows" | 39 #define DW_CLASS_NAME "org/dbsoft/dwindows/DWindows" |
46 | 40 |
47 /* Dynamic Windows internal variables */ | 41 /* Dynamic Windows internal variables */ |
48 static char _dw_app_id[_DW_APP_ID_SIZE+1]= {0}; | 42 static char _dw_app_id[_DW_APP_ID_SIZE+1]= {0}; |
49 static char _dw_app_name[_DW_APP_ID_SIZE+1]= {0}; | 43 static char _dw_app_name[_DW_APP_ID_SIZE+1]= {0}; |
457 retval = htmlchangedfunc(handler->window, DW_POINTER_TO_INT(params[3]), uri, handler->data); | 451 retval = htmlchangedfunc(handler->window, DW_POINTER_TO_INT(params[3]), uri, handler->data); |
458 break; | 452 break; |
459 } | 453 } |
460 } | 454 } |
461 } | 455 } |
462 #ifdef _DW_EVENT_THREADING | |
463 /* Free the memory we allocated for this tread */ | |
464 if(params[1]) | |
465 free(params[1]); | |
466 if(params[2]) | |
467 free(params[2]); | |
468 free(params); | |
469 #endif | |
470 return retval; | 456 return retval; |
471 } | 457 } |
472 | 458 |
473 /* If we aren't using threading, we create a queue of events... | 459 /* We create a queue of events... the oldest event indexed by |
474 * the oldest event indexed by _dw_event_head, the newest by | 460 * _dw_event_head, the newest by _dw_event_tail. |
475 * _dw_event_tail. | 461 */ |
476 */ | |
477 #ifndef _DW_EVENT_THREADING | |
478 #define _DW_EVENT_QUEUE_LENGTH 10 | 462 #define _DW_EVENT_QUEUE_LENGTH 10 |
479 void *_dw_event_queue[_DW_EVENT_QUEUE_LENGTH][_DW_EVENT_PARAM_SIZE]; | 463 void *_dw_event_queue[_DW_EVENT_QUEUE_LENGTH][_DW_EVENT_PARAM_SIZE]; |
480 int _dw_event_head = -1, _dw_event_tail = -1, _dw_main_active = TRUE; | 464 int _dw_event_head = -1, _dw_event_tail = -1, _dw_main_active = TRUE; |
481 HMTX _dw_event_mutex = nullptr; | 465 HMTX _dw_event_mutex = nullptr; |
482 DWTID _dw_main_thread = -1; | 466 DWTID _dw_main_thread = -1; |
557 dw_event_post(_dw_main_event); | 541 dw_event_post(_dw_main_event); |
558 } | 542 } |
559 dw_mutex_unlock(_dw_event_mutex); | 543 dw_mutex_unlock(_dw_event_mutex); |
560 return retval; | 544 return retval; |
561 } | 545 } |
562 #endif | |
563 | 546 |
564 int _dw_event_handler(jobject object, void **params) | 547 int _dw_event_handler(jobject object, void **params) |
565 { | 548 { |
566 int messageid = DW_POINTER_TO_INT(params[8]); | 549 int messageid = DW_POINTER_TO_INT(params[8]); |
567 DWSignalHandler *handler = _dw_get_handler(object, messageid); | 550 DWSignalHandler *handler = _dw_get_handler(object, messageid); |
574 * If it isn't a draw event, either queue the event | 557 * If it isn't a draw event, either queue the event |
575 * or launch a new thread to handle it. | 558 * or launch a new thread to handle it. |
576 */ | 559 */ |
577 if(DW_POINTER_TO_INT(params[8]) != _DW_EVENT_EXPOSE) | 560 if(DW_POINTER_TO_INT(params[8]) != _DW_EVENT_EXPOSE) |
578 { | 561 { |
579 #ifdef _DW_EVENT_THREADING | |
580 /* Make a copy of the params so it isn't allocated from the stack */ | |
581 void *newparams = calloc(_DW_EVENT_PARAM_SIZE, sizeof(void *)); | |
582 | |
583 memcpy(newparams, params, _DW_EVENT_PARAM_SIZE * sizeof(void *)); | |
584 dw_thread_new((void *) _dw_event_handler2, newparams, 0); | |
585 #else | |
586 /* Push the new event onto the queue if it fits */ | 562 /* Push the new event onto the queue if it fits */ |
587 _dw_queue_event(params); | 563 _dw_queue_event(params); |
588 #endif | |
589 } | 564 } |
590 else | 565 else |
591 return _dw_event_handler2(params); | 566 return _dw_event_handler2(params); |
592 | 567 |
593 } /* If we don't have a handler, destroy the window */ | 568 } /* If we don't have a handler, destroy the window */ |
601 */ | 576 */ |
602 JNIEXPORT jint JNICALL | 577 JNIEXPORT jint JNICALL |
603 Java_org_dbsoft_dwindows_DWindows_eventHandler(JNIEnv* env, jobject obj, jobject obj1, jobject obj2, | 578 Java_org_dbsoft_dwindows_DWindows_eventHandler(JNIEnv* env, jobject obj, jobject obj1, jobject obj2, |
604 jint message, jstring str1, jstring str2, | 579 jint message, jstring str1, jstring str2, |
605 jint inta, jint intb, jint intc, jint intd) { | 580 jint inta, jint intb, jint intc, jint intd) { |
606 #ifdef _DW_EVENT_THREADING | |
607 char *utf81 = str1 ? strdup(env->GetStringUTFChars(str1, nullptr)) : nullptr; | |
608 char *utf82 = str2 ? strdup(env->GetStringUTFChars(str2, nullptr)) : nullptr; | |
609 #else | |
610 const char *utf81 = str1 ? env->GetStringUTFChars(str1, nullptr) : nullptr; | 581 const char *utf81 = str1 ? env->GetStringUTFChars(str1, nullptr) : nullptr; |
611 const char *utf82 = str2 ? env->GetStringUTFChars(str2, nullptr) : nullptr; | 582 const char *utf82 = str2 ? env->GetStringUTFChars(str2, nullptr) : nullptr; |
612 #endif | |
613 void *params[_DW_EVENT_PARAM_SIZE] = { DW_POINTER(obj2), DW_POINTER(utf81), DW_POINTER(utf82), | 583 void *params[_DW_EVENT_PARAM_SIZE] = { DW_POINTER(obj2), DW_POINTER(utf81), DW_POINTER(utf82), |
614 DW_INT_TO_POINTER(inta), DW_INT_TO_POINTER(intb), | 584 DW_INT_TO_POINTER(inta), DW_INT_TO_POINTER(intb), |
615 DW_INT_TO_POINTER(intc), DW_INT_TO_POINTER(intd), nullptr, | 585 DW_INT_TO_POINTER(intc), DW_INT_TO_POINTER(intd), nullptr, |
616 DW_INT_TO_POINTER(message), nullptr }; | 586 DW_INT_TO_POINTER(message), nullptr }; |
617 | 587 |
641 | 611 |
642 /* Handlers for HTML events */ | 612 /* Handlers for HTML events */ |
643 JNIEXPORT void JNICALL | 613 JNIEXPORT void JNICALL |
644 Java_org_dbsoft_dwindows_DWindows_eventHandlerHTMLResult(JNIEnv* env, jobject obj, jobject obj1, | 614 Java_org_dbsoft_dwindows_DWindows_eventHandlerHTMLResult(JNIEnv* env, jobject obj, jobject obj1, |
645 jint message, jstring htmlResult, jlong data) { | 615 jint message, jstring htmlResult, jlong data) { |
646 #ifdef _DW_EVENT_THREADING | |
647 char *result = strdup(env->GetStringUTFChars(htmlResult, nullptr)); | |
648 #else | |
649 const char *result = env->GetStringUTFChars(htmlResult, nullptr); | 616 const char *result = env->GetStringUTFChars(htmlResult, nullptr); |
650 #endif | |
651 void *params[_DW_EVENT_PARAM_SIZE] = { nullptr, DW_POINTER(result), nullptr, nullptr, nullptr, nullptr, nullptr, | 617 void *params[_DW_EVENT_PARAM_SIZE] = { nullptr, DW_POINTER(result), nullptr, nullptr, nullptr, nullptr, nullptr, |
652 DW_INT_TO_POINTER(data), DW_INT_TO_POINTER(message), nullptr }; | 618 DW_INT_TO_POINTER(data), DW_INT_TO_POINTER(message), nullptr }; |
653 | 619 |
654 _dw_event_handler(obj1, params); | 620 _dw_event_handler(obj1, params); |
655 } | 621 } |
656 | 622 |
657 JNIEXPORT void JNICALL | 623 JNIEXPORT void JNICALL |
658 Java_org_dbsoft_dwindows_DWWebViewClient_eventHandlerHTMLChanged(JNIEnv* env, jobject obj, jobject obj1, | 624 Java_org_dbsoft_dwindows_DWWebViewClient_eventHandlerHTMLChanged(JNIEnv* env, jobject obj, jobject obj1, |
659 jint message, jstring URI, jint status) { | 625 jint message, jstring URI, jint status) { |
660 #ifdef _DW_EVENT_THREADING | |
661 char *uri = strdup(env->GetStringUTFChars(URI, nullptr)); | |
662 #else | |
663 const char *uri = env->GetStringUTFChars(URI, nullptr); | 626 const char *uri = env->GetStringUTFChars(URI, nullptr); |
664 #endif | |
665 void *params[_DW_EVENT_PARAM_SIZE] = { nullptr, DW_POINTER(uri), nullptr, DW_INT_TO_POINTER(status), | 627 void *params[_DW_EVENT_PARAM_SIZE] = { nullptr, DW_POINTER(uri), nullptr, DW_INT_TO_POINTER(status), |
666 nullptr, nullptr, nullptr, nullptr, DW_INT_TO_POINTER(message), nullptr }; | 628 nullptr, nullptr, nullptr, nullptr, DW_INT_TO_POINTER(message), nullptr }; |
667 | 629 |
668 _dw_event_handler(obj1, params); | 630 _dw_event_handler(obj1, params); |
669 } | 631 } |
767 } | 729 } |
768 | 730 |
769 JNIEXPORT void JNICALL | 731 JNIEXPORT void JNICALL |
770 Java_org_dbsoft_dwindows_DWindows_eventHandlerContainer(JNIEnv* env, jobject obj, jobject obj1, | 732 Java_org_dbsoft_dwindows_DWindows_eventHandlerContainer(JNIEnv* env, jobject obj, jobject obj1, |
771 jint message, jstring jtitle, jint x, jint y, jlong data) { | 733 jint message, jstring jtitle, jint x, jint y, jlong data) { |
772 #ifdef _DW_EVENT_THREADING | |
773 char *title = jtitle ? strdup(env->GetStringUTFChars(jtitle, nullptr)) : nullptr; | |
774 #else | |
775 const char *title = jtitle ? env->GetStringUTFChars(jtitle, nullptr) : nullptr; | 734 const char *title = jtitle ? env->GetStringUTFChars(jtitle, nullptr) : nullptr; |
776 #endif | |
777 void *params[_DW_EVENT_PARAM_SIZE] = { nullptr, DW_POINTER(title), nullptr, DW_INT_TO_POINTER(x), DW_INT_TO_POINTER(y), | 735 void *params[_DW_EVENT_PARAM_SIZE] = { nullptr, DW_POINTER(title), nullptr, DW_INT_TO_POINTER(x), DW_INT_TO_POINTER(y), |
778 nullptr, nullptr, DW_POINTER(data), DW_INT_TO_POINTER(message), nullptr }; | 736 nullptr, nullptr, DW_POINTER(data), DW_INT_TO_POINTER(message), nullptr }; |
779 | 737 |
780 _dw_event_handler(obj1, params); | 738 _dw_event_handler(obj1, params); |
781 } | 739 } |
782 | 740 |
783 JNIEXPORT void JNICALL | 741 JNIEXPORT void JNICALL |
784 Java_org_dbsoft_dwindows_DWindows_eventHandlerTree(JNIEnv* env, jobject obj, jobject obj1, | 742 Java_org_dbsoft_dwindows_DWindows_eventHandlerTree(JNIEnv* env, jobject obj, jobject obj1, |
785 jint message, jobject item, jstring jtitle, jlong data) { | 743 jint message, jobject item, jstring jtitle, jlong data) { |
786 #ifdef _DW_EVENT_THREADING | |
787 char *title = jtitle ? strdup(env->GetStringUTFChars(jtitle, nullptr)) : nullptr; | |
788 #else | |
789 const char *title = jtitle ? env->GetStringUTFChars(jtitle, nullptr) : nullptr; | 744 const char *title = jtitle ? env->GetStringUTFChars(jtitle, nullptr) : nullptr; |
790 #endif | |
791 void *params[_DW_EVENT_PARAM_SIZE] = { DW_POINTER(item), DW_POINTER(title), nullptr, nullptr, nullptr, | 745 void *params[_DW_EVENT_PARAM_SIZE] = { DW_POINTER(item), DW_POINTER(title), nullptr, nullptr, nullptr, |
792 nullptr, nullptr, DW_POINTER(data), DW_INT_TO_POINTER(message), nullptr }; | 746 nullptr, nullptr, DW_POINTER(data), DW_INT_TO_POINTER(message), nullptr }; |
793 | 747 |
794 _dw_event_handler(obj1, params); | 748 _dw_event_handler(obj1, params); |
795 } | 749 } |
804 } | 758 } |
805 | 759 |
806 JNIEXPORT void JNICALL | 760 JNIEXPORT void JNICALL |
807 Java_org_dbsoft_dwindows_DWindows_eventHandlerKey(JNIEnv *env, jobject obj, jobject obj1, jint message, jint ch, | 761 Java_org_dbsoft_dwindows_DWindows_eventHandlerKey(JNIEnv *env, jobject obj, jobject obj1, jint message, jint ch, |
808 jint vk, jint modifiers, jstring str) { | 762 jint vk, jint modifiers, jstring str) { |
809 #ifdef _DW_EVENT_THREADING | |
810 char *cstr = str ? strdup(env->GetStringUTFChars(str, nullptr)) : nullptr; | |
811 #else | |
812 const char *cstr = str ? env->GetStringUTFChars(str, nullptr) : nullptr; | 763 const char *cstr = str ? env->GetStringUTFChars(str, nullptr) : nullptr; |
813 #endif | |
814 void *params[_DW_EVENT_PARAM_SIZE] = { nullptr, DW_POINTER(cstr), nullptr, DW_INT_TO_POINTER(ch), DW_INT_TO_POINTER(vk), | 764 void *params[_DW_EVENT_PARAM_SIZE] = { nullptr, DW_POINTER(cstr), nullptr, DW_INT_TO_POINTER(ch), DW_INT_TO_POINTER(vk), |
815 DW_INT_TO_POINTER(modifiers), nullptr, nullptr, DW_INT_TO_POINTER(message), nullptr }; | 765 DW_INT_TO_POINTER(modifiers), nullptr, nullptr, DW_INT_TO_POINTER(message), nullptr }; |
816 | 766 |
817 _dw_event_handler(obj1, params); | 767 _dw_event_handler(obj1, params); |
818 } | 768 } |
964 // Call the method on the object | 914 // Call the method on the object |
965 env->CallVoidMethod(_dw_obj, dwMain); | 915 env->CallVoidMethod(_dw_obj, dwMain); |
966 _dw_jni_check_exception(env); | 916 _dw_jni_check_exception(env); |
967 } | 917 } |
968 | 918 |
969 #ifdef _DW_EVENT_THREADING | |
970 /* We don't actually run a loop here, | |
971 * we launched a new thread to run the loop there. | |
972 * Just wait for dw_main_quit() on the DWMainEvent. | |
973 */ | |
974 dw_event_wait(_dw_main_event, DW_TIMEOUT_INFINITE); | |
975 #else | |
976 | |
977 /* Save our thread ID, so we know if we should handle | 919 /* Save our thread ID, so we know if we should handle |
978 * events in callback dw_main_sleep/iteration() calls. | 920 * events in callback dw_main_sleep/iteration() calls. |
979 */ | 921 */ |
980 _dw_main_thread = dw_thread_id(); | 922 _dw_main_thread = dw_thread_id(); |
981 | 923 |
994 */ | 936 */ |
995 dw_event_wait(_dw_main_event, 100); | 937 dw_event_wait(_dw_main_event, 100); |
996 | 938 |
997 } while(_dw_main_active); | 939 } while(_dw_main_active); |
998 _dw_main_thread = -1; | 940 _dw_main_thread = -1; |
999 #endif | |
1000 } | 941 } |
1001 | 942 |
1002 /* | 943 /* |
1003 * Causes running dw_main() to return. | 944 * Causes running dw_main() to return. |
1004 */ | 945 */ |
1005 void API dw_main_quit(void) | 946 void API dw_main_quit(void) |
1006 { | 947 { |
1007 #ifndef _DW_EVENT_THREADING | |
1008 _dw_main_active = FALSE; | 948 _dw_main_active = FALSE; |
1009 #endif | |
1010 dw_event_post(_dw_main_event); | 949 dw_event_post(_dw_main_event); |
1011 } | 950 } |
1012 | 951 |
1013 /* | 952 /* |
1014 * Runs a message loop for Dynamic Windows, for a period of milliseconds. | 953 * Runs a message loop for Dynamic Windows, for a period of milliseconds. |
1017 */ | 956 */ |
1018 void API dw_main_sleep(int milliseconds) | 957 void API dw_main_sleep(int milliseconds) |
1019 { | 958 { |
1020 JNIEnv *env; | 959 JNIEnv *env; |
1021 | 960 |
1022 #ifndef _DW_EVENT_THREADING | |
1023 /* If we are in an event callback from dw_main() ... | 961 /* If we are in an event callback from dw_main() ... |
1024 * we need to continue handling events from the UI. | 962 * we need to continue handling events from the UI. |
1025 */ | 963 */ |
1026 if(_dw_main_thread == dw_thread_id()) | 964 if(_dw_main_thread == dw_thread_id()) |
1027 { | 965 { |
1048 | 986 |
1049 gettimeofday(&tv, NULL); | 987 gettimeofday(&tv, NULL); |
1050 | 988 |
1051 } while(_dw_main_active && (difference = ((tv.tv_sec - start.tv_sec)*1000) + ((tv.tv_usec - start.tv_usec)/1000)) <= milliseconds); | 989 } while(_dw_main_active && (difference = ((tv.tv_sec - start.tv_sec)*1000) + ((tv.tv_usec - start.tv_usec)/1000)) <= milliseconds); |
1052 } | 990 } |
1053 else | 991 else if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) |
1054 #endif | |
1055 if((env = (JNIEnv *)pthread_getspecific(_dw_env_key))) | |
1056 { | 992 { |
1057 // First get the class that contains the method you need to call | 993 // First get the class that contains the method you need to call |
1058 jclass clazz = _dw_find_class(env, DW_CLASS_NAME); | 994 jclass clazz = _dw_find_class(env, DW_CLASS_NAME); |
1059 // Get the method that you want to call | 995 // Get the method that you want to call |
1060 jmethodID mainSleep = env->GetMethodID(clazz, "mainSleep", | 996 jmethodID mainSleep = env->GetMethodID(clazz, "mainSleep", |
1068 /* | 1004 /* |
1069 * Processes a single message iteration and returns. | 1005 * Processes a single message iteration and returns. |
1070 */ | 1006 */ |
1071 void API dw_main_iteration(void) | 1007 void API dw_main_iteration(void) |
1072 { | 1008 { |
1073 #ifndef _DW_EVENT_THREADING | |
1074 if(_dw_main_thread == dw_thread_id()) | 1009 if(_dw_main_thread == dw_thread_id()) |
1075 { | 1010 { |
1076 void *params[_DW_EVENT_PARAM_SIZE]; | 1011 void *params[_DW_EVENT_PARAM_SIZE]; |
1077 | 1012 |
1078 /* Dequeue a single pending event */ | 1013 /* Dequeue a single pending event */ |
1079 if (_dw_dequeue_event(params)) | 1014 if (_dw_dequeue_event(params)) |
1080 _dw_event_handler2(params); | 1015 _dw_event_handler2(params); |
1081 } | 1016 } |
1082 else | 1017 else |
1083 #endif | |
1084 /* If we sleep for 0 milliseconds... we will drop out | 1018 /* If we sleep for 0 milliseconds... we will drop out |
1085 * of the loop at the first idle moment | 1019 * of the loop at the first idle moment |
1086 */ | 1020 */ |
1087 dw_main_sleep(0); | 1021 dw_main_sleep(0); |
1088 } | 1022 } |
1089 | 1023 |
1090 /* | 1024 /* |
1091 * Cleanly terminates a DW session, should be signal handler safe. | 1025 * Cleanly terminates a DW session, should be signal handler safe. |
1092 * Parameters: | 1026 * Parameters: |