summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authornagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-06-09 15:50:24 +0000
committernagai <nagai@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2003-06-09 15:50:24 +0000
commit1a28365c0ad995a14d894824c2c4765d41416dab (patch)
tree30ea723b3b590882d2a468493328596a1a9140ff /ext
parent879d09b6f82c409ae1653f1cb09ae4ec7baf96a3 (diff)
renew Tk.mainloop
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3923 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext')
-rw-r--r--ext/tcltklib/tcltklib.c90
1 files changed, 66 insertions, 24 deletions
diff --git a/ext/tcltklib/tcltklib.c b/ext/tcltklib/tcltklib.c
index 41c3a2d314..c8a3e7289d 100644
--- a/ext/tcltklib/tcltklib.c
+++ b/ext/tcltklib/tcltklib.c
@@ -69,13 +69,15 @@ Tcl_Interp *current_interp;
* 'timer_tick' is a limit of one term of thread scheduling.
* If 'timer_tick' == 0, then not use the timer for thread scheduling.
*/
-static int tick_counter;
-#define DEFAULT_EVENT_LOOP_MAX 800
-#define DEFAULT_NO_EVENT_TICK 10
-#define DEFAULT_TIMER_TICK 0
+#define DEFAULT_EVENT_LOOP_MAX 800/*counts*/
+#define DEFAULT_NO_EVENT_TICK 10/*counts*/
+#define DEFAULT_TIMER_TICK 0/*milliseconds*/
+#define DEFAULT_INTERRUPT_TIME 200/*milliseconds*/
static int event_loop_max = DEFAULT_EVENT_LOOP_MAX;
static int no_event_tick = DEFAULT_NO_EVENT_TICK;
static int timer_tick = DEFAULT_TIMER_TICK;
+static int req_timer_tick = DEFAULT_TIMER_TICK;
+static int run_timer_flag = 0;
#if TCL_MAJOR_VERSION >= 8
static int ip_ruby _((ClientData, Tcl_Interp *, int, Tcl_Obj *CONST*));
@@ -95,7 +97,11 @@ _timer_for_tcl(clientData)
struct invoke_queue *q, *tmp;
VALUE thread;
+ DUMP1("called timer_for_tcl");
Tk_DeleteTimerHandler(timer_token);
+
+ run_timer_flag = 1;
+
if (timer_tick > 0) {
timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
(ClientData)0);
@@ -104,7 +110,7 @@ _timer_for_tcl(clientData)
}
/* rb_thread_schedule(); */
- timer_tick += event_loop_max;
+ /* tick_counter += event_loop_max; */
}
static VALUE
@@ -115,13 +121,14 @@ set_eventloop_tick(self, tick)
int ttick = NUM2INT(tick);
if (ttick < 0) {
- rb_raise(rb_eArgError, "timer-tick parameter must be 0 or plus number");
+ rb_raise(rb_eArgError,
+ "timer-tick parameter must be 0 or positive number");
}
/* delete old timer callback */
Tk_DeleteTimerHandler(timer_token);
- timer_tick = ttick;
+ timer_tick = req_timer_tick = ttick;
if (timer_tick > 0) {
/* start timer callback */
timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
@@ -168,37 +175,72 @@ get_eventloop_weight(self)
VALUE
lib_mainloop_core(check_root_widget)
- VALUE check_root_widget;
+ VALUE check_root_widget;
{
- VALUE current = eventloop_thread;
- int check = (check_root_widget == Qtrue);
+ VALUE current = eventloop_thread;
+ int check = (check_root_widget == Qtrue);
+ int tick_counter;
+
+ Tk_DeleteTimerHandler(timer_token);
+ run_timer_flag = 0;
+ if (timer_tick > 0) {
+ timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
+ (ClientData)0);
+ } else {
+ timer_token = (Tcl_TimerToken)NULL;
+ }
+
+ for(;;) {
+ if (rb_thread_alone()) {
+ DUMP1("no other thread");
+ if (timer_tick == 0) {
+ timer_tick = DEFAULT_INTERRUPT_TIME;
+ timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
+ (ClientData)0);
+ }
- Tk_DeleteTimerHandler(timer_token);
- if (timer_tick > 0) {
- timer_token = Tk_CreateTimerHandler(timer_tick, _timer_for_tcl,
- (ClientData)0);
- } else {
- timer_token = (Tcl_TimerToken)NULL;
- }
+ Tcl_DoOneEvent(TCL_ALL_EVENTS);
- for(;;) {
+ if (run_timer_flag) {
+ DUMP1("timer interrupt");
+ run_timer_flag = 0;
+ DUMP1("check Root Widget");
+ if (check && Tk_GetNumMainWindows() == 0) {
+ return Qnil;
+ }
+ }
+
+ } else {
+ DUMP1("there are other threads");
+ timer_tick = req_timer_tick;
tick_counter = 0;
while(tick_counter < event_loop_max) {
- if (Tcl_DoOneEvent(TCL_ALL_EVENTS | (rb_thread_alone() ? 0 : TCL_DONT_WAIT))) {
- tick_counter++;
+ if (Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT)) {
+ tick_counter++;
} else {
- tick_counter += no_event_tick;
+ tick_counter += no_event_tick;
}
+
if (watchdog_thread != 0 && eventloop_thread != current) {
return Qnil;
}
+
+ if (run_timer_flag) {
+ DUMP1("timer interrupt");
+ run_timer_flag = 0;
+ break; /* switch to other thread */
+ }
}
+
+ DUMP1("check Root Widget");
if (check && Tk_GetNumMainWindows() == 0) {
- break;
+ return Qnil;
}
- rb_thread_schedule();
}
- return Qnil;
+
+ rb_thread_schedule();
+ }
+ return Qnil;
}
VALUE