mirror of
https://github.com/python/cpython.git
synced 2025-08-03 00:23:06 +00:00
Added PyMac_SetEventHandler which allows you to replace complete event
handling in inner loop with python code. Also move (previously machine independent) PyErr_CheckSignals here, so we can propagate exceptions in event handling code.
This commit is contained in:
parent
d993648ef6
commit
36ed506f09
1 changed files with 71 additions and 43 deletions
|
@ -107,7 +107,8 @@ extern FSSpec *mfs_GetFSSpecFSSpec();
|
||||||
static int interrupted; /* Set to true when cmd-. seen */
|
static int interrupted; /* Set to true when cmd-. seen */
|
||||||
static RETSIGTYPE intcatcher Py_PROTO((int));
|
static RETSIGTYPE intcatcher Py_PROTO((int));
|
||||||
|
|
||||||
static void PyMac_DoYield Py_PROTO((int, int));
|
static int PyMac_DoYield Py_PROTO((int, int));
|
||||||
|
static int PyMac_Yield Py_PROTO((void));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** These are the real scheduling parameters that control what we check
|
** These are the real scheduling parameters that control what we check
|
||||||
|
@ -129,32 +130,6 @@ struct real_sched_param_struct {
|
||||||
static struct real_sched_param_struct schedparams =
|
static struct real_sched_param_struct schedparams =
|
||||||
{ 1, MAINLOOP_EVENTMASK, 1, 15, 15, 1, 0};
|
{ 1, MAINLOOP_EVENTMASK, 1, 15, 15, 1, 0};
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
** We attempt to be a good citizen by giving up the CPU periodically.
|
|
||||||
** When in the foreground we do this less often and for shorter periods
|
|
||||||
** than when in the background. At this time we also check for events and
|
|
||||||
** pass them off to SIOUX, if compiling with mwerks.
|
|
||||||
** The counts here are in ticks of 1/60th second.
|
|
||||||
** XXXX The initial values here are not based on anything.
|
|
||||||
** FG-python gives up the cpu for 1/60th 5 times per second,
|
|
||||||
** BG-python for .2 second 10 times per second.
|
|
||||||
*/
|
|
||||||
static long interval_fg = 12;
|
|
||||||
static long interval_bg = 6;
|
|
||||||
static long yield_fg = 1;
|
|
||||||
static long yield_bg = 2;
|
|
||||||
static unsigned long lastyield;
|
|
||||||
static int in_foreground;
|
|
||||||
|
|
||||||
/*
|
|
||||||
** When > 0, do full scanning for events (program is not event aware)
|
|
||||||
** when == 0, only scan for Command-period
|
|
||||||
** when < 0, don't do any event scanning
|
|
||||||
*/
|
|
||||||
int PyMac_DoYieldEnabled = 1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Workaround for sioux/gusi combo: set when we are exiting
|
** Workaround for sioux/gusi combo: set when we are exiting
|
||||||
*/
|
*/
|
||||||
|
@ -175,6 +150,11 @@ struct hook_args {
|
||||||
static DlgHookYDUPP myhook_upp;
|
static DlgHookYDUPP myhook_upp;
|
||||||
static int upp_inited = 0;
|
static int upp_inited = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** The python-code event handler
|
||||||
|
*/
|
||||||
|
static PyObject *python_event_handler;
|
||||||
|
|
||||||
#ifdef USE_GUSI
|
#ifdef USE_GUSI
|
||||||
/*
|
/*
|
||||||
** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
|
** GUSI (1.6.0 and earlier, at the least) do not set the MacOS idea of
|
||||||
|
@ -422,23 +402,31 @@ scan_event_queue(flush)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
PyOS_InterruptOccurred()
|
PyErr_CheckSignals()
|
||||||
{
|
{
|
||||||
if (schedparams.enabled) {
|
if (schedparams.enabled) {
|
||||||
if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
|
if ( (unsigned long)LMGetTicks() > schedparams.next_check ) {
|
||||||
PyMac_Yield();
|
if ( PyMac_Yield() < 0)
|
||||||
|
return -1;
|
||||||
schedparams.next_check = (unsigned long)LMGetTicks()
|
schedparams.next_check = (unsigned long)LMGetTicks()
|
||||||
+ schedparams.check_interval;
|
+ schedparams.check_interval;
|
||||||
if (interrupted) {
|
if (interrupted) {
|
||||||
scan_event_queue(1); /* Eat events up to cmd-. */
|
scan_event_queue(1); /* Eat events up to cmd-. */
|
||||||
interrupted = 0;
|
interrupted = 0;
|
||||||
return 1;
|
PyErr_SetNone(PyExc_KeyboardInterrupt);
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PyOS_InterruptOccurred()
|
||||||
|
{
|
||||||
|
scan_event_queue(1);
|
||||||
|
return interrupted;
|
||||||
|
}
|
||||||
/* Check whether we are in the foreground */
|
/* Check whether we are in the foreground */
|
||||||
int
|
int
|
||||||
PyMac_InForeground()
|
PyMac_InForeground()
|
||||||
|
@ -460,19 +448,29 @@ PyMac_InForeground()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PyMac_SetEventHandler(PyObject *evh)
|
||||||
|
{
|
||||||
|
if ( evh && python_event_handler ) {
|
||||||
|
PyErr_SetString(PyExc_RuntimeError, "Python event handler already set");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if ( python_event_handler )
|
||||||
|
Py_DECREF(python_event_handler);
|
||||||
|
if ( evh )
|
||||||
|
Py_INCREF(evh);
|
||||||
|
python_event_handler = evh;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Handle an event, either one found in the mainloop eventhandler or
|
** Handle an event, either one found in the mainloop eventhandler or
|
||||||
** one passed back from the python program.
|
** one passed back from the python program.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
PyMac_HandleEvent(evp, maycallpython)
|
PyMac_HandleEventIntern(evp)
|
||||||
EventRecord *evp;
|
EventRecord *evp;
|
||||||
int maycallpython;
|
|
||||||
{
|
{
|
||||||
|
|
||||||
if ( maycallpython ) {
|
|
||||||
/* To be implemented */
|
|
||||||
}
|
|
||||||
#ifdef __MWERKS__
|
#ifdef __MWERKS__
|
||||||
{
|
{
|
||||||
int siouxdidit;
|
int siouxdidit;
|
||||||
|
@ -493,19 +491,43 @@ PyMac_HandleEvent(evp, maycallpython)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* !__MWERKS__ */
|
#endif /* !__MWERKS__ */
|
||||||
printf("not handled\n");
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Handle an event, either through HandleEvent or by passing it to the Python
|
||||||
|
** event handler.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
PyMac_HandleEvent(evp)
|
||||||
|
EventRecord *evp;
|
||||||
|
{
|
||||||
|
PyObject *rv;
|
||||||
|
|
||||||
|
if ( python_event_handler ) {
|
||||||
|
rv = PyObject_CallFunction(python_event_handler, "(O&)",
|
||||||
|
PyMac_BuildEventRecord, evp);
|
||||||
|
if ( rv )
|
||||||
|
Py_DECREF(rv);
|
||||||
|
else
|
||||||
|
return -1; /* Propagate exception */
|
||||||
|
} else {
|
||||||
|
PyMac_HandleEventIntern(evp);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Yield the CPU to other tasks without processing events.
|
** Yield the CPU to other tasks without processing events.
|
||||||
*/
|
*/
|
||||||
static void
|
static int
|
||||||
PyMac_DoYield(int maxsleep, int maycallpython)
|
PyMac_DoYield(int maxsleep, int maycallpython)
|
||||||
{
|
{
|
||||||
EventRecord ev;
|
EventRecord ev;
|
||||||
int gotone;
|
int gotone;
|
||||||
long latest_time_ready;
|
long latest_time_ready;
|
||||||
|
static int in_here = 0;
|
||||||
|
|
||||||
|
in_here++;
|
||||||
/*
|
/*
|
||||||
** First check for interrupts, if wanted.
|
** First check for interrupts, if wanted.
|
||||||
** This sets a flag that will be picked up at an appropriate
|
** This sets a flag that will be picked up at an appropriate
|
||||||
|
@ -522,27 +544,33 @@ PyMac_DoYield(int maxsleep, int maycallpython)
|
||||||
** - don't process events but do yield
|
** - don't process events but do yield
|
||||||
** - do neither
|
** - do neither
|
||||||
*/
|
*/
|
||||||
if( !schedparams.process_events ) {
|
if( in_here > 1 || !schedparams.process_events ||
|
||||||
|
(python_event_handler && !maycallpython) ) {
|
||||||
if ( maxsleep >= 0 ) {
|
if ( maxsleep >= 0 ) {
|
||||||
SystemTask();
|
SystemTask();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
latest_time_ready = LMGetTicks() + maxsleep;
|
latest_time_ready = LMGetTicks() + maxsleep;
|
||||||
while ( maxsleep >= 0 ) {
|
while ( maxsleep >= 0 ) {
|
||||||
gotone = WaitNextEvent(schedparams.process_events, &ev, 0 /*maxsleep*/, NULL);
|
gotone = WaitNextEvent(schedparams.process_events, &ev, maxsleep, NULL);
|
||||||
/* Get out quickly if nothing interesting is happening */
|
/* Get out quickly if nothing interesting is happening */
|
||||||
if ( !gotone || ev.what == nullEvent )
|
if ( !gotone || ev.what == nullEvent )
|
||||||
break;
|
break;
|
||||||
PyMac_HandleEvent(&ev, maycallpython);
|
if ( PyMac_HandleEvent(&ev) < 0 ) {
|
||||||
|
in_here--;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
maxsleep = latest_time_ready - LMGetTicks();
|
maxsleep = latest_time_ready - LMGetTicks();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
in_here--;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Process events and/or yield the CPU to other tasks if opportune
|
** Process events and/or yield the CPU to other tasks if opportune
|
||||||
*/
|
*/
|
||||||
void
|
int
|
||||||
PyMac_Yield() {
|
PyMac_Yield() {
|
||||||
unsigned long maxsleep;
|
unsigned long maxsleep;
|
||||||
|
|
||||||
|
@ -551,7 +579,7 @@ PyMac_Yield() {
|
||||||
else
|
else
|
||||||
maxsleep = schedparams.bg_yield;
|
maxsleep = schedparams.bg_yield;
|
||||||
|
|
||||||
PyMac_DoYield(maxsleep, 1);
|
return PyMac_DoYield(maxsleep, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue