00001 #include "bcrepeater.h" 00002 #include "bcsignals.h" 00003 #include "bcwindow.h" 00004 #include "condition.h" 00005 00006 #include <unistd.h> 00007 00008 BC_Repeater::BC_Repeater(BC_WindowBase *top_level, long delay) 00009 : Thread() 00010 { 00011 set_synchronous(1); 00012 pause_lock = new Condition(0, "BC_Repeater::pause_lock"); 00013 startup_lock = new Condition(0, "BC_Repeater::startup_lock"); 00014 repeat_lock = new Condition(1, "BC_Repeater::repeat_lock"); 00015 repeating = 0; 00016 interrupted = 0; 00017 this->delay = delay; 00018 this->top_level = top_level; 00019 00020 } 00021 00022 BC_Repeater::~BC_Repeater() 00023 { 00024 interrupted = 1; 00025 pause_lock->unlock(); 00026 repeat_lock->unlock(); 00027 00028 Thread::end(); 00029 Thread::join(); 00030 00031 delete pause_lock; 00032 delete startup_lock; 00033 delete repeat_lock; 00034 } 00035 00036 void BC_Repeater::initialize() 00037 { 00038 start(); 00039 // This is important. It doesn't unblock until the thread is running. 00040 startup_lock->lock("BC_Repeater::initialize"); 00041 } 00042 00043 int BC_Repeater::start_repeating() 00044 { 00045 //printf("BC_Repeater::start_repeating 1 %d\n", delay); 00046 repeating++; 00047 if(repeating == 1) 00048 { 00049 // Resume the loop 00050 pause_lock->unlock(); 00051 } 00052 return 0; 00053 } 00054 00055 int BC_Repeater::stop_repeating() 00056 { 00057 // Recursive calling happens when mouse wheel is used. 00058 if(repeating > 0) 00059 { 00060 repeating--; 00061 // Pause the loop 00062 if(repeating == 0) pause_lock->lock("BC_Repeater::stop_repeating"); 00063 } 00064 return 0; 00065 } 00066 00067 void BC_Repeater::run() 00068 { 00069 //printf("BC_Repeater::run 1 %d\n", getpid()); 00070 next_delay = delay; 00071 Thread::disable_cancel(); 00072 startup_lock->unlock(); 00073 00074 while(!interrupted) 00075 { 00076 Thread::enable_cancel(); 00077 timer.delay(next_delay); 00078 Thread::disable_cancel(); 00079 //if(next_delay <= 0) printf("BC_Repeater::run delay=%d next_delay=%d\n", delay, next_delay); 00080 00081 // Test exit conditions 00082 if(interrupted) return; 00083 // Busy wait here 00084 // if(repeating <= 0) continue; 00085 00086 // Test for pause 00087 pause_lock->lock("BC_Repeater::run"); 00088 pause_lock->unlock(); 00089 timer.update(); 00090 00091 // Test exit conditions 00092 if(interrupted) return; 00093 if(repeating <= 0) continue; 00094 00095 // Wait for existing signal to be processed before sending a new one 00096 repeat_lock->lock("BC_Repeater::run"); 00097 00098 // Test exit conditions 00099 if(interrupted) 00100 { 00101 repeat_lock->unlock(); 00102 return; 00103 } 00104 if(repeating <= 0) 00105 { 00106 repeat_lock->unlock(); 00107 continue; 00108 } 00109 00110 // Wait for window to become available. 00111 top_level->lock_window("BC_Repeater::run"); 00112 00113 // Test exit conditions 00114 if(interrupted) 00115 { 00116 repeat_lock->unlock(); 00117 top_level->unlock_window(); 00118 return; 00119 } 00120 if(repeating <= 0) 00121 { 00122 repeat_lock->unlock(); 00123 top_level->unlock_window(); 00124 continue; 00125 } 00126 00127 // Stick event into queue 00128 top_level->arm_repeat(delay); 00129 top_level->unlock_window(); 00130 next_delay = delay - timer.get_difference(); 00131 if(next_delay <= 0) next_delay = 0; 00132 00133 // Test exit conditions 00134 if(interrupted) 00135 { 00136 repeat_lock->unlock(); 00137 return; 00138 } 00139 if(repeating <= 0) 00140 { 00141 repeat_lock->unlock(); 00142 continue; 00143 } 00144 } 00145 }
1.4.4