mirror of
https://github.com/python/cpython.git
synced 2025-09-26 18:29:57 +00:00
- Moved interrupt code to macglue.c
- Added possibility to turn off mainloop event handling - Check interrupts even when not handling events - Be more carefulabout which events we want - Use different method to determine fg/bg
This commit is contained in:
parent
9fc3989c66
commit
ee23d6ec87
3 changed files with 148 additions and 21 deletions
|
@ -28,6 +28,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
|
||||||
char *macstrerror(int); /* strerror with mac errors */
|
char *macstrerror(int); /* strerror with mac errors */
|
||||||
|
|
||||||
|
extern int PyMac_DoYieldEnabled; /* Don't do eventloop when false */
|
||||||
|
|
||||||
extern PyObject *PyMac_OSErrException; /* Exception for OSErr */
|
extern PyObject *PyMac_OSErrException; /* Exception for OSErr */
|
||||||
PyObject *PyMac_GetOSErrException(void); /* Initialize & return it */
|
PyObject *PyMac_GetOSErrException(void); /* Initialize & return it */
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,8 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include "Python.h"
|
#include "Python.h"
|
||||||
#include "macglue.h"
|
#include "macglue.h"
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
static PyObject *MacOS_Error; /* Exception MacOS.Error */
|
static PyObject *MacOS_Error; /* Exception MacOS.Error */
|
||||||
|
|
||||||
|
|
||||||
|
@ -188,6 +190,18 @@ MacOS_SetScheduleTimes(PyObject *self, PyObject *args)
|
||||||
return Py_None;
|
return Py_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
MacOS_EnableAppswitch(PyObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
int enable;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "i", &enable))
|
||||||
|
return NULL;
|
||||||
|
PyMac_DoYieldEnabled = enable;
|
||||||
|
Py_INCREF(Py_None);
|
||||||
|
return Py_None;
|
||||||
|
}
|
||||||
|
|
||||||
static PyMethodDef MacOS_Methods[] = {
|
static PyMethodDef MacOS_Methods[] = {
|
||||||
{"AcceptHighLevelEvent", MacOS_AcceptHighLevelEvent, 1},
|
{"AcceptHighLevelEvent", MacOS_AcceptHighLevelEvent, 1},
|
||||||
{"GetCreatorAndType", MacOS_GetCreatorAndType, 1},
|
{"GetCreatorAndType", MacOS_GetCreatorAndType, 1},
|
||||||
|
@ -196,6 +210,7 @@ static PyMethodDef MacOS_Methods[] = {
|
||||||
{"SetHighLevelEventHandler", MacOS_SetHighLevelEventHandler, 1},
|
{"SetHighLevelEventHandler", MacOS_SetHighLevelEventHandler, 1},
|
||||||
#endif
|
#endif
|
||||||
{"SetScheduleTimes", MacOS_SetScheduleTimes, 1},
|
{"SetScheduleTimes", MacOS_SetScheduleTimes, 1},
|
||||||
|
{"EnableAppswitch", MacOS_EnableAppswitch, 1},
|
||||||
{NULL, NULL} /* Sentinel */
|
{NULL, NULL} /* Sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -33,9 +33,24 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#include <Desk.h>
|
#include <Desk.h>
|
||||||
#include <Traps.h>
|
#include <Traps.h>
|
||||||
|
#include <Processes.h>
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
#ifdef __MWERKS__
|
#ifdef __MWERKS__
|
||||||
|
/*
|
||||||
|
** With MW we can pass the event off to the console window, so
|
||||||
|
** we might as well handle all events.
|
||||||
|
*/
|
||||||
#include <SIOUX.h>
|
#include <SIOUX.h>
|
||||||
|
#define MAINLOOP_EVENTMASK everyEvent
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
** For other compilers we're more careful, since we can't handle
|
||||||
|
** things like updates (and they'll keep coming back if we don't
|
||||||
|
** handle them)
|
||||||
|
*/
|
||||||
|
#define MAINLOOP_EVENTMASK (mDownMask|keyDownMask|osMask)
|
||||||
#endif /* __MWERKS__ */
|
#endif /* __MWERKS__ */
|
||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
@ -47,11 +62,15 @@ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
/* Declared in macfsmodule.c: */
|
/* Declared in macfsmodule.c: */
|
||||||
extern FSSpec *mfs_GetFSSpecFSSpec();
|
extern FSSpec *mfs_GetFSSpecFSSpec();
|
||||||
|
|
||||||
|
/* Interrupt code variables: */
|
||||||
|
static int interrupted; /* Set to true when cmd-. seen */
|
||||||
|
static RETSIGTYPE intcatcher Py_PROTO((int));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** We attempt to be a good citizen by giving up the CPU periodically.
|
** 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
|
** 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
|
** than when in the background. At this time we also check for events and
|
||||||
** pass them off to stdwin (or SIOUX, if compiling with mwerks).
|
** pass them off to SIOUX, if compiling with mwerks.
|
||||||
** The counts here are in ticks of 1/60th second.
|
** The counts here are in ticks of 1/60th second.
|
||||||
** XXXX The initial values here are not based on anything.
|
** XXXX The initial values here are not based on anything.
|
||||||
** FG-python gives up the cpu for 1/60th 5 times per second,
|
** FG-python gives up the cpu for 1/60th 5 times per second,
|
||||||
|
@ -61,7 +80,11 @@ static long interval_fg = 12;
|
||||||
static long interval_bg = 6;
|
static long interval_bg = 6;
|
||||||
static long yield_fg = 1;
|
static long yield_fg = 1;
|
||||||
static long yield_bg = 12;
|
static long yield_bg = 12;
|
||||||
static long lastyield, in_background;
|
static long lastyield;
|
||||||
|
static int in_foreground;
|
||||||
|
|
||||||
|
int PyMac_DoYieldEnabled = 1; /* Don't do eventloop when false */
|
||||||
|
|
||||||
|
|
||||||
/* Convert C to Pascal string. Returns pointer to static buffer. */
|
/* Convert C to Pascal string. Returns pointer to static buffer. */
|
||||||
unsigned char *
|
unsigned char *
|
||||||
|
@ -137,6 +160,97 @@ PyMac_Error(OSErr err)
|
||||||
return PyErr_Mac(PyMac_GetOSErrException(), err);
|
return PyErr_Mac(PyMac_GetOSErrException(), err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The catcher routine (which may not be used for all compilers) */
|
||||||
|
static RETSIGTYPE
|
||||||
|
intcatcher(sig)
|
||||||
|
int sig;
|
||||||
|
{
|
||||||
|
interrupted = 1;
|
||||||
|
signal(SIGINT, intcatcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
PyOS_InitInterrupts()
|
||||||
|
{
|
||||||
|
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
|
||||||
|
signal(SIGINT, intcatcher);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This routine scans the event queue looking for cmd-.
|
||||||
|
** This is the only way to get an interrupt under THINK (since it
|
||||||
|
** doesn't do SIGINT handling), but is also used under MW, when
|
||||||
|
** the full-fledged event loop is disabled. This way, we can at least
|
||||||
|
** interrupt a runaway python program.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
scan_event_queue(flush)
|
||||||
|
int flush;
|
||||||
|
{
|
||||||
|
register EvQElPtr q;
|
||||||
|
|
||||||
|
q = (EvQElPtr) GetEvQHdr()->qHead;
|
||||||
|
|
||||||
|
for (; q; q = (EvQElPtr)q->qLink) {
|
||||||
|
if (q->evtQWhat == keyDown &&
|
||||||
|
(char)q->evtQMessage == '.' &&
|
||||||
|
(q->evtQModifiers & cmdKey) != 0) {
|
||||||
|
if ( flush )
|
||||||
|
FlushEvents(keyDownMask, 0);
|
||||||
|
interrupted = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PyOS_InterruptOccurred()
|
||||||
|
{
|
||||||
|
#ifdef THINK_C
|
||||||
|
scan_event_queue(1);
|
||||||
|
#endif
|
||||||
|
PyMac_Yield();
|
||||||
|
if (interrupted) {
|
||||||
|
interrupted = 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* intrpeek() is like intrcheck(), but it doesn't flush the events. The
|
||||||
|
** idea is that you call intrpeek() somewhere in a busy-wait loop, and return
|
||||||
|
** None as soon as it returns 1. The mainloop will then pick up the cmd-. soon
|
||||||
|
** thereafter.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
intrpeek()
|
||||||
|
{
|
||||||
|
#ifdef THINK_C
|
||||||
|
scan_event_queue(0);
|
||||||
|
#endif
|
||||||
|
return interrupted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check whether we are in the foreground */
|
||||||
|
int
|
||||||
|
PyMac_InForeground()
|
||||||
|
{
|
||||||
|
static ProcessSerialNumber ours;
|
||||||
|
static inited;
|
||||||
|
ProcessSerialNumber curfg;
|
||||||
|
Boolean eq;
|
||||||
|
|
||||||
|
if ( inited == 0 )
|
||||||
|
(void)GetCurrentProcess(&ours);
|
||||||
|
inited = 1;
|
||||||
|
if ( GetFrontProcess(&curfg) < 0 )
|
||||||
|
eq = 1;
|
||||||
|
else if ( SameProcess(&ours, &curfg, &eq) < 0 )
|
||||||
|
eq = 1;
|
||||||
|
return (int)eq;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Set yield timeouts
|
** Set yield timeouts
|
||||||
*/
|
*/
|
||||||
|
@ -158,7 +272,6 @@ PyMac_DoYield()
|
||||||
EventRecord ev;
|
EventRecord ev;
|
||||||
WindowPtr wp;
|
WindowPtr wp;
|
||||||
long yield;
|
long yield;
|
||||||
extern int StdwinIsActive;
|
|
||||||
static int no_waitnextevent = -1;
|
static int no_waitnextevent = -1;
|
||||||
int gotone;
|
int gotone;
|
||||||
|
|
||||||
|
@ -167,33 +280,30 @@ PyMac_DoYield()
|
||||||
NGetTrapAddress(_Unimplemented, ToolTrap));
|
NGetTrapAddress(_Unimplemented, ToolTrap));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( StdwinIsActive )
|
if ( !PyMac_DoYieldEnabled ) {
|
||||||
|
#ifndef THINK_C
|
||||||
|
/* Under think this has been done before in intrcheck() or intrpeek() */
|
||||||
|
scan_event_queue(0);
|
||||||
|
#endif
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ( in_background )
|
in_foreground = PyMac_InForeground();
|
||||||
yield = yield_bg;
|
if ( in_foreground )
|
||||||
else
|
|
||||||
yield = yield_fg;
|
yield = yield_fg;
|
||||||
|
else
|
||||||
|
yield = yield_bg;
|
||||||
while ( 1 ) {
|
while ( 1 ) {
|
||||||
if ( no_waitnextevent ) {
|
if ( no_waitnextevent ) {
|
||||||
SystemTask();
|
SystemTask();
|
||||||
gotone = GetNextEvent(0xffff, &ev);
|
gotone = GetNextEvent(MAINLOOP_EVENTMASK, &ev);
|
||||||
} else {
|
} else {
|
||||||
gotone = WaitNextEvent(everyEvent, &ev, yield, NULL);
|
gotone = WaitNextEvent(MAINLOOP_EVENTMASK, &ev, yield, 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;
|
||||||
|
|
||||||
/* Check whether we've moved to foreground or background */
|
|
||||||
if ( ev.what == osEvt &&
|
|
||||||
(ev.message & osEvtMessageMask) == (suspendResumeMessage<<24)) {
|
|
||||||
if ( ev.message & resumeFlag ) {
|
|
||||||
in_background = 0;
|
|
||||||
} else {
|
|
||||||
in_background = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifdef __MWERKS__
|
#ifdef __MWERKS__
|
||||||
/* If SIOUX wants it we're done too */
|
/* If SIOUX wants it we're done too */
|
||||||
(void)SIOUXHandleOneEvent(&ev);
|
(void)SIOUXHandleOneEvent(&ev);
|
||||||
|
@ -215,10 +325,10 @@ void
|
||||||
PyMac_Yield() {
|
PyMac_Yield() {
|
||||||
long iv;
|
long iv;
|
||||||
|
|
||||||
if ( in_background )
|
if ( in_foreground )
|
||||||
iv = interval_bg;
|
|
||||||
else
|
|
||||||
iv = interval_fg;
|
iv = interval_fg;
|
||||||
|
else
|
||||||
|
iv = interval_bg;
|
||||||
if ( TickCount() > lastyield + iv )
|
if ( TickCount() > lastyield + iv )
|
||||||
PyMac_DoYield();
|
PyMac_DoYield();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue